typedef struct Node{ unsigned long long id; void *value; int if_setvalue; struct Node *next; struct Node *last; }Node; typedef struct List{ Node *head; Node *tail; unsigned long long length; }List; int safeMode(int ifon);//Safe mode is used to make sure that all malloced will be freed. int releaseAll(void); List *init_list(void); Node *init_node(void); int init_value(Node *,void *); unsigned long long getId(void); int insertInHead(List *p_list, Node *p_node); int insertInTail(List *p_list, Node *p_node); int removeById(List *p_list, unsigned long id); int removeByNode(List *p_list, Node *p_node); int popFromHead(List *p_list); int popFromTail(List *p_list); unsigned long long len(List *p_list); Node *findById(List *p_list, const unsigned long long id); Node *findByValue(List *p_list, const char *type, const void *value); int releaseList(List *p_list); int releaseNode(Node *p_node); int isListEmpty(List *p_list); /*Something about safe mode*/ int if_safeMode = 0; List *node_list = NULL; //Store nodes which haven't been freed. List *list_list = NULL; //Store lists which haven't been freed. int safeMode(int ifon){ if(ifon == 1){ if (node_list == NULL && list_list == NULL){ node_list = (List *)malloc(sizeof(List)); list_list = (List *)malloc(sizeof(List)); if_safeMode = 1; } else{ return -1; } } return ifon; } int releaseAll(void){ if(if_safeMode == 1){ if_safeMode = 0; releaseList(node_list); releaseList(list_list); } return 0; } Node *init_node(void){ Node *p_node = (Node *) malloc(sizeof(Node)); p_node->id = getId(); p_node->if_setvalue = 0; if(if_safeMode) insertInTail(node_list,p_node); return p_node; } List *init_list(void){ List *p_list = (List *) malloc(sizeof(List)); p_list->head = NULL; p_list->tail = NULL; if(if_safeMode){ Node *p_node = init_node(); init_value(p_node,(void *)p_list); insertInTail(list_list,p_node); } return p_list; } int init_value(Node *p_node,void * p_value){ p_node->if_setvalue = 1; p_node->value = p_value; return 0; } unsigned long long getId(void){ unsigned long long id = 0; srand(time(0)); id = ((random()%9)+1)*10; for(int i = 0; i < 18; i++){ id = random()%10; id *= 10; } return id; } int insertInHead(List *p_list, Node *p_node){ if( isListEmpty(p_list) ){ p_list->head = p_node; p_list->tail = p_node; } else{ p_list->head->last = p_node; p_node->last = NULL; p_node->next = p_list->head; p_list->head = p_node; } return 0; } int insertInTail(List *p_list, Node *p_node){ if( isListEmpty(p_list) ){ p_list->head = p_node; p_list->tail = p_node; } else{ p_list->tail->next = p_node; p_node->next = NULL; p_node->last = p_list->tail; p_list->tail = p_node; } return 0; } int releaseNode(Node *p_node){ if(if_safeMode == 1){ removeByNode(node_list,p_node); } if(p_node->if_setvalue == 1){ free(p_node->value); } free(p_node); return 0; } int releaseList(List *p_list){ Node *p_node, *pl_node; p_node = p_list->head; if(if_safeMode == 1){ Node *tar_list = findByValue(list_list,"int",(void *)p_list); removeByNode(list_list,tar_list); } while (p_node != NULL){ pl_node = p_node; p_node = p_node->next; releaseNode(pl_node); } free(p_list); return 0; } int removeById(List *p_list, unsigned long id){ Node *tmp = p_list->head; if( isListEmpty(p_list) ) return -1; do{ if(tmp->id == id) { tmp->last->next = tmp->next; tmp->next->last = tmp->last; releaseNode(tmp); return 1;//found } else{ tmp = tmp->next; } }while(tmp != NULL); return 0;//not find } int removeByNode(List *p_list, Node *p_node){ Node *tmp = p_list->head; if( isListEmpty(p_list) ) return -1; do{ if(tmp == p_node){ tmp->last->next = tmp->next; tmp->next->last = tmp->last; releaseNode(tmp); return 1;//found } else{ tmp = tmp->next; } }while(tmp != NULL); return 0;//not find } int popFromHead(List *p_list){ if( isListEmpty(p_list) ) return -1; else{ Node *tmp = p_list->head; p_list->head->next->last = NULL; p_list->head = p_list->head->next; releaseNode(tmp); } if( isListEmpty(p_list) ){ p_list->head = NULL; p_list->tail = NULL; } return 0; } int popFromTail(List *p_list){ if( isListEmpty(p_list) ) return -1; else{ Node *tmp = p_list->tail; p_list->tail->last->next = NULL; p_list->tail = p_list->tail->last; releaseNode(tmp); } if( isListEmpty(p_list) ){ p_list->head = NULL; p_list->tail = NULL; } return 0; } /*The method in this function won't be better than going through the list * node by node.The worst situation happens when the matched node is in * the middle of the list.*/ Node *findById(List *p_list, const unsigned long long id){ Node *ph_node = p_list->head; Node *pt_node = p_list->tail; int direction = 0; while(ph_node != pt_node){ if (direction == 0){ if (ph_node->id == id){ return ph_node; } else{ ph_node = ph_node->next; } direction = 1; } else{ if (pt_node->id == id){ return pt_node; } else{ pt_node = pt_node->last; } } } return NULL; } Node *findByValue(List *p_list, const char *type, const void *value){ Node *p_node = p_list->head; while(p_node != NULL){ if(!strcmp(type,"int")){ if(*((int *)p_node) == *((int *)value)){ return p_node; } } else if(!strcmp(type,"double")){ if(*((double *)p_node) == *((double *)value)){ return p_node; } } else if(!strcmp (type,"string")){ if(!strcmp((char *)p_node->value,(char *)value)) { return p_node; } } else{ return NULL; } } return NULL; } int isListEmpty(List *p_list){ if(p_list->head == NULL || p_list->tail == NULL)// If its head or tail is NULL,it would be thought as empty. return 1; // But we should ensure that both of them are NULL when we return 0; // want to make a list empty. }