// email_management_system.c // Tammy Zhong // Implementation file for email management system functions // (TODO) #include #include #include #include "email_management_system.h" // Function prototypes // Internal functions // Used by insertion operations struct email *create_email(char sender[MAX_LEN], char subject[MAX_LEN], double size, enum email_type type, int priority); // like create_node // Used by `delete_email_of_priority` for commented out approach // void delete_specific_email(struct folder *email_folder, char subject[MAX_LEN]); // Used by `split_folder` struct folder *insert_email_at_tail(struct folder *email_folder, char sender[MAX_LEN], char subject[MAX_LEN], double size, enum email_type type, int priority); // Function definitions // Creates a new empty email folder // Similar to previous lecture code create_node struct folder *create_folder(char name[MAX_LEN]) { struct folder *new_folder = malloc(sizeof(struct folder)); strcpy(new_folder->name, name); new_folder->num_emails = 0; new_folder->emails = NULL; return new_folder; } // Creates and initialises a new email // Internal function used by insertion operations // Similar to previous lecture code create_node struct email *create_email(char sender[MAX_LEN], char subject[MAX_LEN], double size, enum email_type type, int priority) { struct email *new_email = malloc(sizeof(struct email)); strcpy(new_email->sender, sender); strcpy(new_email->subject, subject); new_email->size = size; new_email->type = type; new_email->priority = priority; new_email->next = NULL; // important return new_email; } // Add a new email to the folder at the head // Similar to previous lecture code insert_head struct folder *insert_email_at_head(struct folder *email_folder, char sender[MAX_LEN], char subject[MAX_LEN], double size, enum email_type type, int priority) { // create email struct email *new_email = create_email(sender, subject, size, type, priority); email_folder->num_emails++; // if there are no emails if (email_folder->emails == NULL) { email_folder->emails = new_email; return email_folder; } new_email->next = email_folder->emails; email_folder->emails = new_email; return email_folder; } // Prints out details of a single email void print_single_email(struct email *email) { if (email == NULL) { printf("Email is NULL.\n"); } printf("Sender: %s\n", email->sender); printf("Subject: %s\n", email->subject); printf("Size: %lfmb\n", email->size); printf("Type: "); if (email->type == RECEIVED) { printf("RECEIVED\n"); } else if (email->type == SENT) { printf("SENT\n"); } else if (email->type == DRAFT) { printf("DRAFT\n"); } else { printf("UNKNOWN\n"); } printf("Priority: "); if (email->priority == HIGH_PRIORITY) { printf("HIGH_PRIORITY\n"); } else if (email->priority == NORMAL_PRIORITY) { printf("NORMAL_PRIORITY\n"); } else if (email->priority == LOW_PRIORITY) { printf("LOW_PRIORITY\n"); } else { printf("UNKNOWN\n"); } } // Print/display all emails in folder // Similar to previous lecture code print_list void print_emails(struct folder *email_folder) { printf("Folder Name: %s\n", email_folder->name); struct email *current = email_folder->emails; if (current == NULL) { printf("There are no emails in this folder.\n"); } while (current != NULL) { printf("---\n"); print_single_email(current); current = current->next; } } // Returns number of emails in a given folder // (TODO: Improve this) int count_emails(struct folder *email_folder) { // int counter = 0; // struct email *current = email_folder->emails; // while (current != NULL) { // counter++; // current = current->next; // } // return counter; return email_folder->num_emails; } // Given a string, look for email where the subject is this string struct email *search_email(struct folder *email_folder, char subject[MAX_LEN]) { struct email *current = email_folder->emails; while (current != NULL) { // compare the email's subject with the given subject // if we find the email with the given subject if (strcmp(current->subject, subject) == 0) { return current; } current = current->next; } // cannot be found return NULL; } // Remove email(s) with certain priority (e.g. filter out low priority emails) void delete_email_of_priority(struct folder *email_folder, int priority) { // Loop through the folder of emails // if we encounter email of given priority // call a function that deletes one node, // delete_specific_email(folder, subject); // loop through the list // only catering for when the emails we want to delete // are at the head while (email_folder->emails != NULL && email_folder->emails->priority == priority) { struct email *temp = email_folder->emails; email_folder->emails = temp->next; free(temp); email_folder->num_emails--; } if (email_folder->emails == NULL) { // nothing to remove anymore return; } // email_folder->emails->priority != priority // but we still have emails in this list struct email *current = email_folder->emails; // loop through and check the next node of // current to see if it's one we want to delete while (current->next != NULL) { // if the next one is the one we want to delete if (current->next->priority == priority) { struct email *temp = current->next; current->next = temp->next; // current->next = current->next->next; free(temp); email_folder->num_emails--; // here we have already changed current->next // so it points at the element after // when we try and delete } else { current = current->next; } } } // Append emails from folder_2 after folder_1 and returns them in the one folder // Assumption made here assumes not same subject email in folder_1 and folder_2 struct folder *merge_folders(char merged_folder_name[MAX_LEN], struct folder *folder_1, struct folder *folder_2) { // NOTE: this is my solution, we did not go through this in the lecture :) // if folder_1->emails is empty then we can't do folder_1->emails->next if (folder_1->emails == NULL) { // change the details of folder_2, namely name to new name strcpy(folder_2->name, merged_folder_name); return folder_2; } // Loop to end of first list to change next ptr of last node struct email *current = folder_1->emails; while (current->next != NULL) { current = current->next; } // current at the last node current->next = folder_2->emails; // change data in folder_1 node to update to new name we want strcpy(folder_1->name, merged_folder_name); // folder_1->num_emails = folder_1->num_emails + folder_2->num_emails; free(folder_2); // important since it was a malloc-ed node we don't need return folder_1; } // CHALLENGE at home for fun: Sort emails in folder based on size // (slightly out of scope of COMP1511 - touches on sorting algorithms) // order doesn't matter if two emails of same size void sort_emails(struct folder *email_folder) { // NOTE: this is my solution, we did not go through this in the lecture :) struct email* current; struct email* last = NULL; // Check for empty list if (email_folder->emails == NULL) return; int swapped = 1; while (swapped == 1) { swapped = 0; current = email_folder->emails; // Traverse the list while (current->next != last) { // If the current node's data is greater than the next node's data, swap them if (current->size > current->next->size) { int temp = current->size; current->size = current->next->size; current->next->size = temp; swapped = 1; } current = current->next; } // Move the last pointer to the second last node as the // last element is sorted last = current; } } // Inserts email at tail - Internal Function // Similar to previous lecture code on insert_at_tail (no need to write this one in lecture) struct folder *insert_email_at_tail(struct folder *email_folder, char sender[MAX_LEN], char subject[MAX_LEN], double size, enum email_type type, int priority) { struct email *new_email = create_email(sender, subject, size, type, priority); email_folder->num_emails++; // empty list case if (email_folder->emails == NULL) { email_folder->emails = new_email; return email_folder; } struct email *current = email_folder->emails; // loop the current pointer until the last node while (current->next != NULL) { current = current->next; } // at this pt, current->next == NULL // which means current is pointing at the last node current->next = new_email; return email_folder; } // Split emails in a given folder into 3 folders based on email type // keeping original ordering // assumption: inbox, sent and draft are folders already malloc-ed and initialised void split_folder(struct folder *given_folder, struct folder *inbox, struct folder *sent, struct folder *draft) { // NOTE: this is my solution, we did not go through this in the lecture :) // There are other approaches to this, but I have chosen to show this way // to show you can make use of existing linked list functions if (given_folder->emails == NULL) { // nothing to split return; } // (new lists are given to us, assume NULL) // go through and add each of them into the new list, making a copy struct email *current = given_folder->emails; while (current != NULL) { if (current->type == RECEIVED) { insert_email_at_tail(inbox, current->sender, current->subject, current->size, current->type, current->priority); // inbox->num_emails++; } else if (current->type == SENT) { insert_email_at_tail(sent, current->sender, current->subject, current->size, current->type, current->priority); // sent->num_emails++; } else if (current->type == DRAFT) { insert_email_at_tail(draft, current->sender, current->subject, current->size, current->type, current->priority); // draft->num_emails++; } else { // shouldn't happen } current = current->next; } // now we've got them in three split list, // we can remove original list // which will need function following.. clear_folder(given_folder); } // Removes all emails from a folder // clears and delete associated memory of folder and emails in it void clear_folder(struct folder *email_folder) { struct email *current = email_folder->emails; // loop through delete each email we encounter while (current != NULL) { struct email *temp = current; current = current->next; free(temp); } free(email_folder); }