#include "kwic.h" #include "line_storage.h" // Each line is a list of word_nodes typedef struct word_node { char* word; struct word_node* next_word_ptr; } word_node; typedef word_node* word_node_ptr; // The Line Storage module stores a list of line_nodes typedef struct line_node { struct line_node* next_line_ptr; word_node_ptr head_word_ptr; word_node_ptr tail_word_ptr; int word_count; } line_node; typedef line_node* line_node_ptr; static line_node_ptr head_line_ptr,tail_line_ptr; static int line_count; /* state invariant * 1. if line_count == 0 then * head_line_ptr == NULL * tail_line_ptr == NULL * else * head_line_ptr points to a null-terminated linked list of line_nodes. * tail_line_ptr points to the last line_node in this list. * There are line_count line_nodes in this list. * * 2. for every line_node allocated by Line Storage * if word_count == 0 then * head_word_ptr == NULL * tail_word_ptr == NULL * else * head_word_ptr points to a null-terminated linked list of word_nodes. * tail_word_ptr points to the last word_node in this list. * There are word_count word_nodes in this list. * * 3. For every word_node allocated, word is a null-terminated array of char. * * 4. All of the dynamic memory allocated by Line Storage (and not yet freed) * is in the list structure headed by head_line_ptr. */ /* * Purpose: * if head_line_ptr contains at least i+1 line_nodes then * return the address of the ith line_node * else * return NULL * Precondition * the state invariant holds */ static line_node_ptr get_line(int i) { line_node_ptr tmp_line_ptr; if (i < 0) return NULL; for (tmp_line_ptr = head_line_ptr; i-- > 0 && tmp_line_ptr != NULL; tmp_line_ptr = tmp_line_ptr->next_line_ptr) printf("get_line: %d\n",tmp_line_ptr->word_count); return tmp_line_ptr; } /* * Purpose: * if word_node_ptr != NULL && list headed by word_node_ptr has >= i words then * return pointer to the ith word in list headed by word_node_ptr * else * return NULL * Precondition: * the state invariant holds * word_node_ptr is either NULL or a pointer to a list of word_nodes */ static word_node_ptr get_word(word_node_ptr word_node_ptr,int i) { if (i < 0) return NULL; while (i-- > 0 && word_node_ptr != NULL) { printf("get_word: %s\n",word_node_ptr->word); word_node_ptr = word_node_ptr->next_word_ptr; } return word_node_ptr; } /** @purpose initialize the module with 0 lines return the appropriate KWIC status code @preconditions none */ int ls_init(void) { head_line_ptr = NULL; tail_line_ptr = NULL; line_count = 0; return KW_SUCCESS; } /** @purpose add a line, containing no words, in position ls_num_lines() if not enough memory is available to add a new line return KW_MEMORY_ERROR else return KW_SUCCESS @preconditions ls_init has been called and returned KW_SUCCESS */ int ls_add_line(void) { line_node_ptr new_line_ptr; // create and fill a line_node new_line_ptr = malloc(sizeof(line_node)); printf("malloc called\n"); if (new_line_ptr == NULL) return KW_MEMORY_ERROR; line_count++; new_line_ptr->next_line_ptr = NULL; new_line_ptr->head_word_ptr = NULL; new_line_ptr->tail_word_ptr = NULL; new_line_ptr->word_count = 0; // link in the new line_node if (tail_line_ptr == NULL) { head_line_ptr = new_line_ptr; } else { tail_line_ptr->next_line_ptr = new_line_ptr; } tail_line_ptr = new_line_ptr; return KW_SUCCESS; } /** @purpose if ls_num_lines() == 0 return KW_RANGE_ERROR else if not enough memory is available to store word return KW_MEMORY_ERROR else add word to the end of line ls_num_lines()-1 return KW_SUCCESS @preconditions ls_init has been called and returned KW_SUCCESS */ int ls_add_word(char* word) { word_node_ptr new_word_ptr; if (tail_line_ptr == NULL) return KW_RANGE_ERROR; // create and fill a word_node new_word_ptr = malloc(sizeof(word_node)); printf("malloc called\n"); if (new_word_ptr == NULL) return KW_MEMORY_ERROR; new_word_ptr->word = malloc(strlen(word)+1); printf("malloc called\n"); if (new_word_ptr->word == NULL) { free(new_word_ptr); return KW_MEMORY_ERROR; } tail_line_ptr->word_count++; strcpy(new_word_ptr->word,word); new_word_ptr->next_word_ptr = NULL; // link in the new word_node if (tail_line_ptr->tail_word_ptr == NULL) { // empty line tail_line_ptr->head_word_ptr = new_word_ptr; } else { tail_line_ptr->tail_word_ptr->next_word_ptr = new_word_ptr; } tail_line_ptr->tail_word_ptr = new_word_ptr; return KW_SUCCESS; } /** @purpose if lineNum in [0..ls_num_lines()-1] and word_num in [0..ls_num_words()-1] return word word_num from line lineNum else return NULL @preconditions ls_init has been called and returned KW_SUCCESS */ const char* ls_get_word(int lineNum,int word_num) { line_node_ptr tmp_line_ptr; word_node_ptr tmp_word_ptr; if (lineNum >= line_count) return NULL; // find line LineNum tmp_line_ptr = get_line(lineNum); if (tmp_line_ptr == NULL) return NULL; // find word word_num tmp_word_ptr = get_word(tmp_line_ptr->head_word_ptr,word_num); if (tmp_word_ptr == NULL) return NULL; return tmp_word_ptr->word; } /** @purpose return the total number of lines currently stored @preconditions ls_init has been called and returned KW_SUCCESS */ int ls_num_lines(void) { return line_count; } /** @purpose if lineNum in [0..ls_num_lines()-1] return the number of words in line lineNum else return KW_RANGE_ERROR @preconditions ls_init has been called and returned KW_SUCCESS */ int ls_num_words(int lineNum) { line_node_ptr tmp_line_ptr; tmp_line_ptr = get_line(lineNum); if (tmp_line_ptr == NULL) { return KW_RANGE_ERROR; } return tmp_line_ptr->word_count; }