diff --git a/algorithms/C/linked-lists/gl-threads.c b/algorithms/C/linked-lists/gl-threads.c index dbee48e0..b81f452f 100644 --- a/algorithms/C/linked-lists/gl-threads.c +++ b/algorithms/C/linked-lists/gl-threads.c @@ -31,25 +31,12 @@ * @author [Ashborn-SM](https://github.com/Ashborn-SM) */ -#include -#include -#include +#include // for dynamic memory allocation +#include // for IO operations +#include // for string manipulation #define HEAD(list) (list->head) #define OFFSETOF(structure, field) (long)&((structure*)0)->field -#define POP_FRONT(list, structure, offset){ \ - glthread_node* _cur = HEAD(list), *temp = HEAD(list)->next; \ - structure* per = (structure*)((char*)_cur - offset); \ - free(per); \ - HEAD(list) = temp; \ -} -#define ITERATE_GL_THREADS_BEGIN(lstptr, struct_type, ptr) \ -{ \ - glthread_node *_glnode = NULL, *_next = NULL; \ - for(_glnode = lstptr->head; _glnode; _glnode = _next){ \ - _next = _glnode->next; \ - ptr = (struct_type *)((char *)_glnode - lstptr->offset); -#define END }} /** * @struct glthread_node @@ -65,14 +52,18 @@ typedef struct glthread_node_{ * @brief the doubly linked-list */ typedef struct{ - glthread_node* head; - unsigned int offset; + glthread_node* head; + size_t size; + // store the addresses of all the nodes in linked-list + char** addresses; + unsigned int offset; }gldll; /** * @brief initialise the node * @details set the node members to NULL * @param node linked-list node + * @returns void */ void init_glthread_node(glthread_node* node){ node->next = NULL; @@ -84,9 +75,12 @@ void init_glthread_node(glthread_node* node){ * @details set the head and offset * @param list linked-list * @param offset offset of the data member + * @returns void */ void init_glthread_list(gldll* list, unsigned int offset){ list->head = NULL; + list->size = 0; + list->addresses = NULL; list->offset = offset; } @@ -95,9 +89,11 @@ void init_glthread_list(gldll* list, unsigned int offset){ * @details insert the node at the front of the list * @param list linked-list * @param node node to be inserted + * @returns void */ void glthread_pushfront(gldll* list, glthread_node* node){ glthread_node* cur = HEAD(list); + list->size++; if(cur == NULL){ HEAD(list) = node; return; @@ -107,6 +103,47 @@ void glthread_pushfront(gldll* list, glthread_node* node){ HEAD(list) = node; } +/** + * @brief delete the node at front + * @details delete the head node and point the head to the next node + * @param list based doubly linked-list + * @returns void + */ +void glthread_popfront(gldll* list){ + if(list == NULL || HEAD(list) == NULL ){ return; } + glthread_node* temp = HEAD(list)->next; + free((char*)HEAD(list) - list->offset); + HEAD(list) = temp; + if(HEAD(list) != NULL){ + temp->prev = NULL; + } + list->size--; +} + +/** + * @brief return the addresses of all nodes in the linked-list + * @param list based doubly linked-list + * @return addresses of all nodes in the linked-list starting from head + */ +char** get_addresses(gldll* list){ + if(list->addresses != NULL){ + // free the memory in order to avoid memory leak + free(list->addresses); + } + list->addresses = malloc(list->size*sizeof(char*)); + if(list->addresses == NULL){ + printf("Allocation Failure"); + exit(0); + } + glthread_node* cur = HEAD(list); + for(int i=0; cur != NULL; i++){ + list->addresses[i] = (char*)cur - list->offset; + cur = cur->next; + } + + return list->addresses; +} + /** * @struct person * @brief a structure with attributes of a person @@ -120,6 +157,7 @@ typedef struct{ /** * @brief print the details of the person * @param per person structure + * @returns void */ void print(person* per){ printf("Name: %s\n", per->name); @@ -143,101 +181,108 @@ person* allocate(){ } /** - * @brief test the program + * @brief Self-test the implementation * @param list linked-list + * @returns void */ -void test(gldll* list){ +static void test(gldll* list){ + if(HEAD(list) == NULL){ + return; + } char passed[10] = "[PASSED]:\0"; char failed[10] = "[FAILED]:\0"; char expected[9] = "EXPECTED\0"; char returned[9] = "RETURNED\0"; - glthread_node* cur = HEAD(list); - person* per = NULL; - ITERATE_GL_THREADS_BEGIN(list, person, per){ - if(strcmp(per->name, "rohit") == 0){ - printf("%s: %s -> %s, %s -> %s\n", passed, expected, "rohit", - returned, per->name); - } - else{ - printf("%s: %s -> %s, %s -> %s\n", failed, expected, "rohit", - returned, per->name); - } - if(per->age == 23){ - printf("%s: %s -> %i, %s -> %i\n", passed, expected, 23, - returned, per->age); - } - else{ - printf("%s: %s -> %i, %s -> %i\n", failed, expected, 23, - returned, per->age); - } - if(per->height == 174){ - printf("%s: %s -> %i, %s -> %i\n", passed, expected, 174, - returned, per->height); - } - else{ - printf("%s: %s -> %i, %s -> %i\n", failed, expected, 174, - returned, per->height); - } - if(per->weight == 67){ - printf("%s: %s -> %i, %s -> %i\n", passed, expected, 67, - returned, per->weight); - } - else{ - printf("%s: %s -> %i, %s -> %i\n", failed, expected, 67, - returned, per->weight); - } - break; - }END; + person* per = (person*)((char*)HEAD(list)- list->offset); + if(strcmp(per->name, "rohit") == 0){ + printf("%s: %s -> %s, %s -> %s\n", passed, expected, "rohit", + returned, per->name); + } + else{ + printf("%s: %s -> %s, %s -> %s\n", failed, expected, "rohit", + returned, per->name); + } + if(per->age == 23){ + printf("%s: %s -> %i, %s -> %i\n", passed, expected, 23, + returned, per->age); + } + else{ + printf("%s: %s -> %i, %s -> %i\n", failed, expected, 23, + returned, per->age); + } + if(per->height == 174){ + printf("%s: %s -> %i, %s -> %i\n", passed, expected, 174, + returned, per->height); + } + else{ + printf("%s: %s -> %i, %s -> %i\n", failed, expected, 174, + returned, per->height); + } + if(per->weight == 67){ + printf("%s: %s -> %i, %s -> %i\n", passed, expected, 67, + returned, per->weight); + } + else{ + printf("%s: %s -> %i, %s -> %i\n", failed, expected, 67, + returned, per->weight); + } } +/** + * @brief free all the memory allocated for the doubly linked-list + * @param list doubly linked-list + * @returns void + */ +void destructor(gldll** list){ + while(HEAD((*list))!= NULL){ + glthread_popfront((*list)); + } + free(*list); +} + +/** + * @brief Main function + * @returns 0 on exit + */ int main(){ - gldll* list = malloc(sizeof(*list)); + gldll* list = malloc(sizeof(*list)); if(list == NULL){ printf("Allocation Failure"); exit(0); } - person* rahul = allocate(); - person* rohit = allocate(); + person* rahul = allocate(); + person* rohit = allocate(); - strcpy(rahul->name, "rahul"); - strcpy(rohit->name, "rohit"); + strcpy(rahul->name, "rahul"); + strcpy(rohit->name, "rohit"); - rahul->age = 19; - rohit->age = 23; + rahul->age = 19; + rohit->age = 23; - rahul->height = 170; - rohit->height = 174; + rahul->height = 170; + rohit->height = 174; - rahul->weight = 60; - rohit->weight = 67; + rahul->weight = 60; + rohit->weight = 67; - init_glthread_list(list, OFFSETOF(person, glnode)); + init_glthread_list(list, OFFSETOF(person, glnode)); - init_glthread_node(&(rahul->glnode)); - init_glthread_node(&(rohit->glnode)); + init_glthread_node(&(rahul->glnode)); + init_glthread_node(&(rohit->glnode)); - glthread_pushfront(list, &(rohit->glnode)); - glthread_pushfront(list, &(rahul->glnode)); + glthread_pushfront(list, &(rohit->glnode)); + glthread_pushfront(list, &(rahul->glnode)); + + char** addresses = get_addresses(list); + for(int i=0; isize; i++){ + print((person*)addresses[i]); + } + + glthread_popfront(list); - person* temp = NULL; - ITERATE_GL_THREADS_BEGIN(list, person, temp){ - // uncomment the below line to print the details of the person - print(temp); - }END; - /* - Output: - Name: rahul - Height: 170 - Age:19 - Weight: 60 - ------------- - Name: rohit - Height: 174 - Age: 23 - Weight: 77 - ------------- - */ - POP_FRONT(list, person, OFFSETOF(person, glnode)); test(list); + + destructor(&list); + return 0; }