diff --git a/gluethread/LinkedListApi.c b/gluethread/LinkedListApi.c new file mode 100644 index 0000000..8afdc69 --- /dev/null +++ b/gluethread/LinkedListApi.c @@ -0,0 +1,266 @@ + +#include +#include +#include +#include "LinkedListApi.h" +#include + +ll_t* init_singly_ll(){ + return calloc(1, sizeof(ll_t)); +} + +singly_ll_node_t* singly_ll_init_node(void* data){ + singly_ll_node_t* node = calloc(1, sizeof(singly_ll_node_t)); + node->data = data; + return node; +} + +int +singly_ll_add_node(ll_t* ll, singly_ll_node_t *node){ + if(!ll) return -1; + if(!node) return -1; + if(!GET_HEAD_SINGLY_LL(ll)){ + GET_HEAD_SINGLY_LL(ll) = node; + INC_NODE_COUNT_SINGLY_LL(ll); + return 0; + } + + node->next = GET_HEAD_SINGLY_LL(ll); + GET_HEAD_SINGLY_LL(ll) = node; + INC_NODE_COUNT_SINGLY_LL(ll); + return 0; +} + +int +singly_ll_add_node_by_val(ll_t *ll, void* data){ + singly_ll_node_t* node = singly_ll_init_node(data); + return singly_ll_add_node(ll, node); +} + +int +singly_ll_delete_node(ll_t *ll, singly_ll_node_t *node){ + if(!ll) return -1; + if(!GET_HEAD_SINGLY_LL(ll) || !node) return 0; + singly_ll_node_t *trav = NULL; + /*if node is not the last node*/ + if(node->next){ + singly_ll_node_t *temp = NULL; + node->data = node->next->data; + temp = node->next; + node->next = node->next->next; + free(temp); + DEC_NODE_COUNT_SINGLY_LL(ll); + return 0; + } + + /* if node is the only node in LL*/ + if(ll->node_count == 1 && GET_HEAD_SINGLY_LL(ll) == node){ + free(node); + GET_HEAD_SINGLY_LL(ll) = NULL; + DEC_NODE_COUNT_SINGLY_LL(ll); + return 0; + } + + /*if node is the last node of the LL*/ + trav = GET_HEAD_SINGLY_LL(ll); + while(trav->next != node){ + trav = trav->next; + continue; + } + + trav->next = NULL; + free(node); + DEC_NODE_COUNT_SINGLY_LL(ll); + return 0; +} + +int +singly_ll_remove_node(ll_t *ll, singly_ll_node_t *node){ + if(!ll || !GET_HEAD_SINGLY_LL(ll)) return 0; + if(!node){ + printf("%s(%d) : Error : node is NULL\n", __FUNCTION__, __LINE__); + return -1; + } + int i = 0; + singly_ll_node_t *head = GET_HEAD_SINGLY_LL(ll), *prev = NULL; + + if(head == node){ + GET_HEAD_SINGLY_LL(ll) = GET_NEXT_NODE_SINGLY_LL(head); + DEC_NODE_COUNT_SINGLY_LL(ll); + node->next = NULL; + return 0; + } + + prev = head; + head = GET_NEXT_NODE_SINGLY_LL(head); + for(i =1; i < GET_NODE_COUNT_SINGLY_LL(ll); i++){ + if(head != node){ + prev = head; + head = GET_NEXT_NODE_SINGLY_LL(head); + continue; + } + + GET_NEXT_NODE_SINGLY_LL(prev) = GET_NEXT_NODE_SINGLY_LL(head); + GET_NEXT_NODE_SINGLY_LL(head) = NULL; + DEC_NODE_COUNT_SINGLY_LL(ll); + node->next = NULL; + return 0; + } + printf("%s(%d) : Error : node not found\n", __FUNCTION__, __LINE__); + return -1; +} + + + +unsigned int +singly_ll_delete_node_by_value(ll_t *ll, void *data, int size){ + if(!ll || !GET_HEAD_SINGLY_LL(ll)) return 0; + unsigned int curren_node_count = GET_NODE_COUNT_SINGLY_LL(ll); + singly_ll_node_t* trav = GET_HEAD_SINGLY_LL(ll); + while(trav != NULL){ + if(memcmp(trav->data, data, size) == 0){ + singly_ll_delete_node(ll, trav); + return curren_node_count - GET_NODE_COUNT_SINGLY_LL(ll); + } + trav = trav->next; + } + return curren_node_count - GET_NODE_COUNT_SINGLY_LL(ll); +} + + +unsigned int +singly_ll_remove_node_by_value(ll_t *ll, void *data, int size){ + if(!ll || !GET_HEAD_SINGLY_LL(ll)) return 0; + unsigned int curren_node_count = GET_NODE_COUNT_SINGLY_LL(ll); + singly_ll_node_t* trav = GET_HEAD_SINGLY_LL(ll); + while(trav != NULL){ + if(memcmp(trav->data, data, size) == 0){ + singly_ll_remove_node(ll, trav); + return curren_node_count - GET_NODE_COUNT_SINGLY_LL(ll); + } + trav = trav->next; + } + return curren_node_count - GET_NODE_COUNT_SINGLY_LL(ll); +} + + +unsigned int +singly_ll_remove_node_by_dataptr(ll_t *ll, void *data){ + if(!ll || !GET_HEAD_SINGLY_LL(ll)) return 0; + unsigned int curren_node_count = GET_NODE_COUNT_SINGLY_LL(ll); + singly_ll_node_t* trav = GET_HEAD_SINGLY_LL(ll); + while(trav != NULL){ + if(trav->data == data){ + singly_ll_remove_node(ll, trav); + return curren_node_count - GET_NODE_COUNT_SINGLY_LL(ll); + } + trav = trav->next; + } + return curren_node_count - GET_NODE_COUNT_SINGLY_LL(ll); +} + + +singly_ll_node_t* +singly_ll_get_node_by_data_ptr(ll_t *ll, void *data){ + if(!ll || !GET_HEAD_SINGLY_LL(ll)) return NULL; + int i = 0; + singly_ll_node_t *head = GET_HEAD_SINGLY_LL(ll); + + for(; i < GET_NODE_COUNT_SINGLY_LL(ll); i++){ + if(head->data == data) + return head; + head = GET_NEXT_NODE_SINGLY_LL(head); + } + return NULL; +} + + +void print_singly_LL(ll_t *ll){ + if(!ll) { + printf("Invalid Linked List\n"); + return; + } + if(is_singly_ll_empty(ll)){ + printf("Empty Linked List\n"); + return; + } + + singly_ll_node_t* trav = GET_HEAD_SINGLY_LL(ll); + unsigned int i = 0; + printf("node count = %d\n", GET_NODE_COUNT_SINGLY_LL(ll)); + while(trav){ + printf("%d. Data = %p, node = %p\n", i, trav->data, trav); + i++; + trav = trav->next; + } +} + +bool_t +is_singly_ll_empty(ll_t *ll){ + if(!ll) assert(0); + if(ll->node_count == 0) + return LL_TRUE; + return LL_FALSE; +} + +void +reverse_singly_ll(ll_t *ll){ + if(!ll) assert(0) ; + if(is_singly_ll_empty(ll)) return; + if(GET_NODE_COUNT_SINGLY_LL(ll) == 1) return; + singly_ll_node_t *p1 = GET_HEAD_SINGLY_LL(ll), + *p2 = ll->head->next, *p3 = NULL; + p1->next = NULL; + do{ + p3 = p2->next; + p2->next = p1; + p1 = p2; + p2 = p3; + }while(p3); + ll->head = p1; + return; +} + +void +delete_singly_ll(ll_t *ll){ + if(!ll) return; + + if(is_singly_ll_empty(ll)){ + return; + } + + singly_ll_node_t *head = GET_HEAD_SINGLY_LL(ll), + *next = GET_NEXT_NODE_SINGLY_LL(head); + + do{ + free(head); + head = next; + if(next) + next = GET_NEXT_NODE_SINGLY_LL(next); + + } while(head); + + ll->node_count = 0; + ll->head = NULL; +} + +void singly_ll_set_comparison_fn(ll_t *ll, int (*comparison_fn)(void *, void *)){ + + if(!ll) assert(0) ; + ll->comparison_fn = comparison_fn; +} + +void * +singly_ll_search_by_key(ll_t *ll, void *key){ + + assert(ll); + if(!key) + return NULL; + + singly_ll_node_t *list_node = NULL; + ITERATE_LIST(ll, list_node){ + if(ll->comparison_fn(list_node->data, key)) + return list_node->data; + } + return NULL; +} diff --git a/gluethread/LinkedListApi.h b/gluethread/LinkedListApi.h new file mode 100644 index 0000000..7be1eeb --- /dev/null +++ b/gluethread/LinkedListApi.h @@ -0,0 +1,48 @@ +#ifndef __LINKEDLIST__ +#define __LINKEDLIST__ + + +#define GET_HEAD_SINGLY_LL(ll) (ll->head) +#define INC_NODE_COUNT_SINGLY_LL(ll) (ll->node_count++) +#define DEC_NODE_COUNT_SINGLY_LL(ll) (ll->node_count--) +#define GET_NODE_COUNT_SINGLY_LL(ll) (ll->node_count) +#define GET_NEXT_NODE_SINGLY_LL(node) (node->next) + +typedef enum{ + LL_FALSE, + LL_TRUE +} bool_t; + +typedef struct LL_Node{ + void *data; + struct LL_Node *next; +} singly_ll_node_t; + +typedef struct LL{ + unsigned int node_count; + singly_ll_node_t *head; + int (*comparison_fn)(void*, void *); +} ll_t; + +ll_t* init_singly_ll(); +singly_ll_node_t* singly_ll_init_node(void* data); +int singly_ll_add_node(ll_t *ll, singly_ll_node_t *node); +int singly_ll_add_node_by_val(ll_t *ll, void* data); +int singly_ll_remove_node(ll_t *ll, singly_ll_node_t *node); +unsigned int singly_ll_remove_node_by_value(ll_t *ll, void* data, int size); +bool_t is_singly_ll_empty(ll_t *ll); +void print_singly_LL(ll_t *ll); +void reverse_singly_ll(ll_t *ll); +void delete_singly_ll(ll_t *ll); +int singly_ll_delete_node(ll_t *ll, singly_ll_node_t *node); +unsigned int singly_ll_delete_node_by_value(ll_t *ll, void *data, int size); +singly_ll_node_t *singly_ll_get_node_by_data_ptr(ll_t *ll, void *data); +unsigned int singly_ll_remove_node_by_dataptr(ll_t *ll, void *data); +void singly_ll_set_comparison_fn(ll_t *ll, int (*comparison_fn)(void *, void *)); +void * singly_ll_search_by_key(ll_t *ll, void *key); + +#define ITERATE_LIST(list_ptr, node_ptr) \ + node_ptr = GET_HEAD_SINGLY_LL(list_ptr); \ + for(; node_ptr!= NULL; node_ptr = GET_NEXT_NODE_SINGLY_LL(node_ptr))\ + +#endif diff --git a/gluethread/Makefile b/gluethread/Makefile new file mode 100644 index 0000000..66fb557 --- /dev/null +++ b/gluethread/Makefile @@ -0,0 +1,13 @@ +TARGET:liblist.a exe +liblist.a:LinkedListApi.o + ar rs liblist.a LinkedListApi.o +exe:main.o liblist.a + gcc -g main.o -o exe -L . -llist +LinkedListApi.o:LinkedListApi.c + gcc -g -c -I . LinkedListApi.c -o LinkedListApi.o +main.o:main.c + gcc -g -c -I . main.c -o main.o +clean: + rm *.o + rm exe + rm liblist.a diff --git a/gluethread/README.md b/gluethread/README.md new file mode 100644 index 0000000..7031605 --- /dev/null +++ b/gluethread/README.md @@ -0,0 +1,2 @@ +# DevelopLibrary +Develop a Good Customisable General purpose library in C diff --git a/gluethread/glthreads/Makefile b/gluethread/glthreads/Makefile new file mode 100644 index 0000000..016fdb2 --- /dev/null +++ b/gluethread/glthreads/Makefile @@ -0,0 +1,14 @@ +LIBNAME=libglthread.a +TARGET:${LIBNAME} exe +${LIBNAME}:glthread.o + ar rs ${LIBNAME} glthread.o +exe:main.o ${LIBNAME} + gcc -g main.o -o exe -L . -lglthread +glthread.o:glthread.c + gcc -g -c -I . glthread.c -o glthread.o +main.o:main.c + gcc -g -c -I . main.c -o main.o +clean: + rm *.o + rm exe + rm ${LIBNAME} diff --git a/gluethread/glthreads/glthread.c b/gluethread/glthreads/glthread.c new file mode 100644 index 0000000..94cdb50 --- /dev/null +++ b/gluethread/glthreads/glthread.c @@ -0,0 +1,81 @@ +#include "glthread.h" +#include +#include + +/*Private function to add a new_node right after curr_node*/ +static void +_glthread_add_next(glthread_node_t *curr_node, + glthread_node_t *new_node){ + + if(!curr_node->right){ + curr_node->right = new_node; + new_node->left = curr_node; + return; + } + + glthread_node_t *temp = curr_node->right; + curr_node->right = new_node; + new_node->left = curr_node; + new_node->right = temp; + temp->left = new_node; +} + +/*Fn to insert a new GLnode into a glthread at the first position + * in a glthread i.e. new node becomes a head + * */ +void +glthread_add (glthread_t *lst, glthread_node_t *glnode){ + + glnode->left = NULL; + glnode->right = NULL; + if(!lst->head){ + lst->head = glnode; + return; + } + glthread_node_t *head = lst->head; + _glthread_add_next(glnode, head); + lst->head = glnode; +} + +static void +_remove_glthread(glthread_node_t *glnode){ + + if(!glnode->left){ + if(glnode->right){ + glnode->right->left = NULL; + glnode->right = 0; + return; + } + return; + } + if(!glnode->right){ + glnode->left->right = NULL; + glnode->left = NULL; + return; + } + + glnode->left->right = glnode->right; + glnode->right->left = glnode->left; + glnode->left = 0; + glnode->right = 0; +} + +/*API to remove a glnode from glthread*/ +void +glthread_remove(glthread_t *lst, glthread_node_t *glnode){ + + glthread_node_t *head = lst->head; + /*If the node being removed is the head node itself, then update the + * head*/ + if(head == glnode){ + lst->head = head->right; + } + _remove_glthread(glnode); +} + +void +init_glthread(glthread_t *glthread, unsigned int offset){ + + glthread->head = NULL; + glthread->offset = offset; +} diff --git a/gluethread/glthreads/glthread.h b/gluethread/glthreads/glthread.h new file mode 100644 index 0000000..2bd2aa0 --- /dev/null +++ b/gluethread/glthreads/glthread.h @@ -0,0 +1,42 @@ +#ifndef __GLTHREADS__ +#define __GLTHREADS__ + +typedef struct glthread_node_ { + + struct glthread_node_ *left; + struct glthread_node_ *right; +} glthread_node_t; + +typedef struct glthread_ { + + glthread_node_t *head; + unsigned int offset; +} glthread_t; + +void +glthread_add (glthread_t *lst, glthread_node_t *glnode); + +void +glthread_remove(glthread_t *lst, glthread_node_t *glnode); + +/*Iterative macro to Iterate Over GLTHhreads*/ +#define ITERATE_GL_THREADS_BEGIN(lstptr, struct_type, ptr) \ +{ \ + glthread_node_t *_glnode = NULL, *_next = NULL; \ + for(_glnode = lstptr->head; _glnode; _glnode = _next){ \ + _next = _glnode->right; \ + ptr = (struct_type *)((char *)_glnode - lstptr->offset); + +#define ITERATE_GL_THREADS_ENDS }} + +#define glthread_node_init(glnode) \ + glnode->left = NULL; \ + glnode->right = NULL; + +void +init_glthread(glthread_t *glthread, unsigned int offset); + +#define offsetof(struct_name, field_name) \ + ((unsigned int)&((struct_name *)0)->field_name) + +#endif /* __GLTHREADS__ */ diff --git a/gluethread/glthreads/main.c b/gluethread/glthreads/main.c new file mode 100644 index 0000000..a0ec797 --- /dev/null +++ b/gluethread/glthreads/main.c @@ -0,0 +1,87 @@ +#include "glthread.h" +#include +#include +#include + +typedef struct emp_ { + + char name[30]; + unsigned int salary; + char designation[30]; + unsigned int emp_id; + glthread_node_t glnode; +} emp_t; + +void +print_emp_details(emp_t *emp){ + + printf("Employee name = %s\n", emp->name); + printf("salary = %u\n", emp->salary); + printf("designation = %s\n", emp->designation); + printf("emp_id = %u\n", emp->emp_id); +} + + +int +main(int argc, char **argv){ + + emp_t *emp1 = calloc(1, sizeof(emp_t)); + strncpy(emp1->name, "Neha", strlen("Neha")); + emp1->salary = 50000; + strncpy(emp1->designation, "HR", strlen("HR")); + emp1->emp_id = 21; + glthread_node_init((&emp1->glnode)); + + emp_t *emp2 = calloc(1, sizeof(emp_t)); + strncpy(emp2->name, "Abhishek", strlen("Abhishek")); + emp1->salary = 150000; + strncpy(emp2->designation, "SE3", strlen("SE3")); + emp2->emp_id = 32; + glthread_node_init((&emp2->glnode)); + + emp_t *emp3 = calloc(1, sizeof(emp_t)); + strncpy(emp3->name, "Arun", strlen("Arun")); + emp3->salary = 60000; + strncpy(emp3->designation, "SE4", strlen("SE4")); + emp3->emp_id = 27; + glthread_node_init((&emp3->glnode)); + + + /*Now Create a glthread*/ + glthread_t *emp_list = calloc(1, sizeof(glthread_t)); + init_glthread(emp_list, offsetof(emp_t, glnode)); + + /*Now insert the records in glthread*/ + glthread_add(emp_list, &emp1->glnode); + glthread_add(emp_list, &emp2->glnode); + glthread_add(emp_list, &emp3->glnode); + + + /*Walk over glthread*/ + emp_t *ptr = NULL; + ITERATE_GL_THREADS_BEGIN(emp_list, emp_t, ptr){ + + print_emp_details(ptr); + } ITERATE_GL_THREADS_ENDS; + + /*Let us remove one record at random*/ + + glthread_remove(emp_list, &emp2->glnode); + printf("\nprinting again . . . \n"); + + ITERATE_GL_THREADS_BEGIN(emp_list, emp_t, ptr){ + + print_emp_details(ptr); + } ITERATE_GL_THREADS_ENDS; + + + /*Free all Dynamicall allocations*/ + ITERATE_GL_THREADS_BEGIN(emp_list, emp_t, ptr){ + + glthread_remove(emp_list, &ptr->glnode); + free(ptr); + } ITERATE_GL_THREADS_ENDS; + free(emp_list); + + return 0; +} diff --git a/gluethread/glthreads/main2.c b/gluethread/glthreads/main2.c new file mode 100644 index 0000000..a0ec797 --- /dev/null +++ b/gluethread/glthreads/main2.c @@ -0,0 +1,87 @@ +#include "glthread.h" +#include +#include +#include + +typedef struct emp_ { + + char name[30]; + unsigned int salary; + char designation[30]; + unsigned int emp_id; + glthread_node_t glnode; +} emp_t; + +void +print_emp_details(emp_t *emp){ + + printf("Employee name = %s\n", emp->name); + printf("salary = %u\n", emp->salary); + printf("designation = %s\n", emp->designation); + printf("emp_id = %u\n", emp->emp_id); +} + + +int +main(int argc, char **argv){ + + emp_t *emp1 = calloc(1, sizeof(emp_t)); + strncpy(emp1->name, "Neha", strlen("Neha")); + emp1->salary = 50000; + strncpy(emp1->designation, "HR", strlen("HR")); + emp1->emp_id = 21; + glthread_node_init((&emp1->glnode)); + + emp_t *emp2 = calloc(1, sizeof(emp_t)); + strncpy(emp2->name, "Abhishek", strlen("Abhishek")); + emp1->salary = 150000; + strncpy(emp2->designation, "SE3", strlen("SE3")); + emp2->emp_id = 32; + glthread_node_init((&emp2->glnode)); + + emp_t *emp3 = calloc(1, sizeof(emp_t)); + strncpy(emp3->name, "Arun", strlen("Arun")); + emp3->salary = 60000; + strncpy(emp3->designation, "SE4", strlen("SE4")); + emp3->emp_id = 27; + glthread_node_init((&emp3->glnode)); + + + /*Now Create a glthread*/ + glthread_t *emp_list = calloc(1, sizeof(glthread_t)); + init_glthread(emp_list, offsetof(emp_t, glnode)); + + /*Now insert the records in glthread*/ + glthread_add(emp_list, &emp1->glnode); + glthread_add(emp_list, &emp2->glnode); + glthread_add(emp_list, &emp3->glnode); + + + /*Walk over glthread*/ + emp_t *ptr = NULL; + ITERATE_GL_THREADS_BEGIN(emp_list, emp_t, ptr){ + + print_emp_details(ptr); + } ITERATE_GL_THREADS_ENDS; + + /*Let us remove one record at random*/ + + glthread_remove(emp_list, &emp2->glnode); + printf("\nprinting again . . . \n"); + + ITERATE_GL_THREADS_BEGIN(emp_list, emp_t, ptr){ + + print_emp_details(ptr); + } ITERATE_GL_THREADS_ENDS; + + + /*Free all Dynamicall allocations*/ + ITERATE_GL_THREADS_BEGIN(emp_list, emp_t, ptr){ + + glthread_remove(emp_list, &ptr->glnode); + free(ptr); + } ITERATE_GL_THREADS_ENDS; + free(emp_list); + + return 0; +} diff --git a/gluethread/main.c b/gluethread/main.c new file mode 100644 index 0000000..84ea609 --- /dev/null +++ b/gluethread/main.c @@ -0,0 +1,65 @@ +#include +#include +#include "LinkedListApi.h" +#include + +typedef struct person_{ + + char name[32]; + int age; + int weight; +} person_t; + +int +person_comparison_fn(void *struct_ptr, void *key){ + + person_t *person = (person_t *)struct_ptr; + if(strncmp(person->name, (char *)key, strlen((char *)key)) == 0 && + strlen((char *)key) == strlen(person->name)) + return 1; /*Match*/ + return 0;/*Not Match*/ +} + +void +print_person_details(person_t *outperson){ + + printf("outperson->name = %s\n", outperson->name); + printf("outperson->age = %d\n", outperson->age); + printf("outperson->weight = %d\n", outperson->weight); +} + +int +main(int argc, char **argv){ + + ll_t *person_list = init_singly_ll(); + + /*Register comparison fn*/ + person_list->comparison_fn = person_comparison_fn; + + person_t person1 = {"Ram", 30, 68}; + person_t person2 = {"Vibhor", 31, 70}; + person_t person3 = {"Akshay", 32, 56}; + + singly_ll_add_node_by_val(person_list, &person1); + singly_ll_add_node_by_val(person_list, &person2); + singly_ll_add_node_by_val(person_list, &person3); + + person_t *outperson = NULL; + + printf("\n\nSearching ....\n"); + outperson = (person_t *)singly_ll_search_by_key(person_list, "Ram"); + + print_person_details(outperson); + + printf("\n\n Looping ...\n"); + /*using looping macro to iterare*/ + singly_ll_node_t *list_node = NULL; + + ITERATE_LIST(person_list, list_node){ + + outperson = (person_t *)list_node->data; + print_person_details(outperson); + } + return 0; +} +