enh(C): add more functions to gl-threads.c (#566)

pull/575/head
Rahul Rajeev Pillai 2021-10-13 16:37:26 +05:30 committed by GitHub
parent bd97f4e0b4
commit 4f1d1883ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 137 additions and 92 deletions

View File

@ -31,25 +31,12 @@
* @author [Ashborn-SM](https://github.com/Ashborn-SM) * @author [Ashborn-SM](https://github.com/Ashborn-SM)
*/ */
#include <stdlib.h> #include <stdlib.h> // for dynamic memory allocation
#include <stdio.h> #include <stdio.h> // for IO operations
#include <string.h> #include <string.h> // for string manipulation
#define HEAD(list) (list->head) #define HEAD(list) (list->head)
#define OFFSETOF(structure, field) (long)&((structure*)0)->field #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 * @struct glthread_node
@ -65,14 +52,18 @@ typedef struct glthread_node_{
* @brief the doubly linked-list * @brief the doubly linked-list
*/ */
typedef struct{ typedef struct{
glthread_node* head; glthread_node* head;
unsigned int offset; size_t size;
// store the addresses of all the nodes in linked-list
char** addresses;
unsigned int offset;
}gldll; }gldll;
/** /**
* @brief initialise the node * @brief initialise the node
* @details set the node members to NULL * @details set the node members to NULL
* @param node linked-list node * @param node linked-list node
* @returns void
*/ */
void init_glthread_node(glthread_node* node){ void init_glthread_node(glthread_node* node){
node->next = NULL; node->next = NULL;
@ -84,9 +75,12 @@ void init_glthread_node(glthread_node* node){
* @details set the head and offset * @details set the head and offset
* @param list linked-list * @param list linked-list
* @param offset offset of the data member * @param offset offset of the data member
* @returns void
*/ */
void init_glthread_list(gldll* list, unsigned int offset){ void init_glthread_list(gldll* list, unsigned int offset){
list->head = NULL; list->head = NULL;
list->size = 0;
list->addresses = NULL;
list->offset = offset; 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 * @details insert the node at the front of the list
* @param list linked-list * @param list linked-list
* @param node node to be inserted * @param node node to be inserted
* @returns void
*/ */
void glthread_pushfront(gldll* list, glthread_node* node){ void glthread_pushfront(gldll* list, glthread_node* node){
glthread_node* cur = HEAD(list); glthread_node* cur = HEAD(list);
list->size++;
if(cur == NULL){ if(cur == NULL){
HEAD(list) = node; HEAD(list) = node;
return; return;
@ -107,6 +103,47 @@ void glthread_pushfront(gldll* list, glthread_node* node){
HEAD(list) = 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 * @struct person
* @brief a structure with attributes of a person * @brief a structure with attributes of a person
@ -120,6 +157,7 @@ typedef struct{
/** /**
* @brief print the details of the person * @brief print the details of the person
* @param per person structure * @param per person structure
* @returns void
*/ */
void print(person* per){ void print(person* per){
printf("Name: %s\n", per->name); 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 * @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 passed[10] = "[PASSED]:\0";
char failed[10] = "[FAILED]:\0"; char failed[10] = "[FAILED]:\0";
char expected[9] = "EXPECTED\0"; char expected[9] = "EXPECTED\0";
char returned[9] = "RETURNED\0"; char returned[9] = "RETURNED\0";
glthread_node* cur = HEAD(list); person* per = (person*)((char*)HEAD(list)- list->offset);
person* per = NULL; if(strcmp(per->name, "rohit") == 0){
ITERATE_GL_THREADS_BEGIN(list, person, per){ printf("%s: %s -> %s, %s -> %s\n", passed, expected, "rohit",
if(strcmp(per->name, "rohit") == 0){ returned, per->name);
printf("%s: %s -> %s, %s -> %s\n", passed, expected, "rohit", }
returned, per->name); else{
} printf("%s: %s -> %s, %s -> %s\n", failed, expected, "rohit",
else{ returned, per->name);
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,
if(per->age == 23){ returned, per->age);
printf("%s: %s -> %i, %s -> %i\n", passed, expected, 23, }
returned, per->age); else{
} printf("%s: %s -> %i, %s -> %i\n", failed, expected, 23,
else{ returned, per->age);
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,
if(per->height == 174){ returned, per->height);
printf("%s: %s -> %i, %s -> %i\n", passed, expected, 174, }
returned, per->height); else{
} printf("%s: %s -> %i, %s -> %i\n", failed, expected, 174,
else{ returned, per->height);
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,
if(per->weight == 67){ returned, per->weight);
printf("%s: %s -> %i, %s -> %i\n", passed, expected, 67, }
returned, per->weight); else{
} printf("%s: %s -> %i, %s -> %i\n", failed, expected, 67,
else{ returned, per->weight);
printf("%s: %s -> %i, %s -> %i\n", failed, expected, 67, }
returned, per->weight);
}
break;
}END;
} }
/**
* @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(){ int main(){
gldll* list = malloc(sizeof(*list)); gldll* list = malloc(sizeof(*list));
if(list == NULL){ if(list == NULL){
printf("Allocation Failure"); printf("Allocation Failure");
exit(0); exit(0);
} }
person* rahul = allocate(); person* rahul = allocate();
person* rohit = allocate(); person* rohit = allocate();
strcpy(rahul->name, "rahul"); strcpy(rahul->name, "rahul");
strcpy(rohit->name, "rohit"); strcpy(rohit->name, "rohit");
rahul->age = 19; rahul->age = 19;
rohit->age = 23; rohit->age = 23;
rahul->height = 170; rahul->height = 170;
rohit->height = 174; rohit->height = 174;
rahul->weight = 60; rahul->weight = 60;
rohit->weight = 67; 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(&(rahul->glnode));
init_glthread_node(&(rohit->glnode)); init_glthread_node(&(rohit->glnode));
glthread_pushfront(list, &(rohit->glnode)); glthread_pushfront(list, &(rohit->glnode));
glthread_pushfront(list, &(rahul->glnode)); glthread_pushfront(list, &(rahul->glnode));
char** addresses = get_addresses(list);
for(int i=0; i<list->size; 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); test(list);
destructor(&list);
return 0;
} }