diff --git a/UseDataBase.c b/UseDataBase.c index c76ad61db8918f308bb948fdef10c803e39a9a95..1d98322b6631c7e5d108bc8dc74f171dc1690ec6 100644 --- a/UseDataBase.c +++ b/UseDataBase.c @@ -46,25 +46,23 @@ typedef struct { double* hotttnesss; } songs_struct; // Songs struct. -int test_file_bool = 0; // Check if using smaller test csv or not. -int songs_array_max = ARRAY_SIZE; // Saves current size of songs array. -int song_index = 0; // Current song index. -songs_struct** songs_array; // The array which holds all song pointers. +int test_file_bool = 1; // Check if using smaller test csv or not. +int total_song_count; // Total number of songs in database. +songs_struct* song_holder_struct; // The holder of current song data. // Method Declaration. int open_file(); // Initially opens file to read. -void read_songs(); // Reads in songs from database files. -void populate_array(); // Populates array with fields. -void resize_array(); // Increase buffer size of song array. -void print_all_songs(); // Prints info for all songs in array. +void read_song_of_index(); // Gets song value of index. +void get_song_count(); // Gets count of total songs in database. +void free_song_holder(); // Frees memory used by song holder. +void populate_song(); // Populates song holder with fields. void print_song_info(); // Prints all info for provided song. -void print_song_of_index(); // Finds and prints song of given index. +void print_all_songs(); // Prints info for all songs in array. void print_help_text(); // Prints helper text for user. void find_song(); // Find song with given name. songs_struct* search_array_by_song(); // Binary search for name. songs_struct* search_array_by_album(); // Linear search for album. -void exit_program(); // Frees memory and closes program. /** @@ -73,46 +71,19 @@ void exit_program(); // Frees memory and closes program. */ int main(int argc, char* argv[]) { int run_program_bool; // Bool to keep program running. - int song_directory_descriptor; // File descriptor for directory data. - int song_binary_descriptor; // File descriptor for binary song data. int index; // Buffer index; int atoi_index; // Used if user provides song index. - int* song_size; // "Directory" size of current song. char* user_input_buffer; // Buffer of user input. char* temp_buffer; // Temp buffer. char* user_input_string; // Current string of user's input. char* input_to_lower; // User input as all lower. off_t read_value; // Return value of read attempt. - off_t offset_size; // Return value of lseek attempt. // Initialize vars. run_program_bool = 1; - songs_array = calloc(songs_array_max, sizeof(songs_struct *)); - song_size = calloc(1, (sizeof(int) + 1)); - - // Check test csv bool. If true, read smaller csv. - if (test_file_bool) { - song_directory_descriptor = open_file("Data/SongDirectory_Small", O_RDONLY); - song_binary_descriptor = open_file("Data/BinarySongData_Small", O_RDONLY); - } else { // Else use full data set. - song_directory_descriptor = open_file("Data/SongDirectory", O_RDONLY); - song_binary_descriptor = open_file("Data/BinarySongData", O_RDONLY); - } - - // Read songs until no more directories are present. - while ((read_value = read(song_directory_descriptor, song_size, sizeof(int))) != 0) { - if (read_value < 0) { - err_sys("Failed to read line."); - } - - offset_size = lseek(song_directory_descriptor, sizeof(int), SEEK_CUR); - if (offset_size < 0) { - err_sys("Failed to update pointer on read in."); - } - - read_songs(song_binary_descriptor, song_size); - } + song_holder_struct = calloc(1, sizeof(songs_struct)); + get_song_count(); print_help_text(); // Actually run program for user input. @@ -142,7 +113,6 @@ int main(int argc, char* argv[]) { index++; } ++temp_buffer; - //user_input_string = remove_newline(user_input_string); // Read user input and handle accordingly. if ((user_input_string != NULL) && (strcmp(user_input_string, "") != 0)) { @@ -163,7 +133,8 @@ int main(int argc, char* argv[]) { } // Check if song index was provided else if ((atoi_index = atoi(input_to_lower)) != 0) { - print_song_of_index(atoi_index); + read_song_of_index(atoi_index); + print_song_info(); } else { // Attempt to find song with given name. find_song(input_to_lower); @@ -175,11 +146,8 @@ int main(int argc, char* argv[]) { free(user_input_buffer); } - // Free memory and close program. - free(song_size); - close(song_directory_descriptor); - close(song_binary_descriptor); - exit_program(); + // // Free memory and close program. + free_song_holder(); } @@ -196,30 +164,88 @@ int open_file(char* file_location, int operator_flags) { } -/** - * Reads in songs from database files. - */ -void read_songs(int binary_descriptor, int* song_size) { - +void read_song_of_index(int desired_index) { + int song_directory_descriptor; // File descriptor for directory data. + int song_binary_descriptor; // File descriptor for binary song data. + int current_index = 0; + int* song_size; + ssize_t read_value; + off_t offset_size; void* read_buffer; + + song_size = calloc(1, sizeof(int)); read_buffer = calloc(1, BUFFER_SIZE); - ssize_t read_value = read(binary_descriptor, read_buffer, *song_size); - if (read_value < 0) { - err_sys("Failed to read in song."); + + // Check test csv bool. If true, read smaller csv. + if (test_file_bool) { + song_directory_descriptor = open_file("Data/SongDirectory_Small", O_RDONLY); + song_binary_descriptor = open_file("Data/BinarySongData_Small", O_RDONLY); + } else { // Else use full data set. + song_directory_descriptor = open_file("Data/SongDirectory", O_RDONLY); + song_binary_descriptor = open_file("Data/BinarySongData", O_RDONLY); + } + + while (current_index < (desired_index + 1)) { + // Read directory file. + read_value = read(song_directory_descriptor, song_size, sizeof(int)); + if (read_value < 0) { + err_sys("Failed to read line."); + } + + // printf("Index: %d ", current_index); + // printf("Read value: %ld ", read_value); + // printf("Song size: %d\n", *song_size); + + if (current_index < desired_index) { + // Read binary file. + // I don't understand why but this read seems necessary + // or else lseek seems to behave oddly. + // Spent hours on this, am baffled. + read_value = read(song_binary_descriptor, read_buffer, *song_size); + if (read_value < 0) { + err_sys("Failed to read line."); + } + + // Offset directory file. + offset_size = lseek(song_directory_descriptor, sizeof(int), SEEK_CUR); + if (offset_size < 0) { + err_sys("Failed to update pointer on read in."); + } + + // Offset binary file. + offset_size = lseek(song_binary_descriptor, *song_size, SEEK_CUR); + if (offset_size < 0) { + err_sys("Failed to update pointer on read in."); + } + } + current_index++; } - off_t offset_size = lseek(binary_descriptor, *song_size, SEEK_CUR); - if (offset_size < 0) { - err_sys("Failed to update pointer on read in."); + // Read binary file. + read_value = read(song_binary_descriptor, read_buffer, *song_size); + if (read_value < 0) { + err_sys("Failed to read line."); } - populate_array(song_size, read_buffer); + // printf("Read value: %ld\n", read_value); + // printf("Buffer value: %s\n\n", read_buffer); + + + // Populate song struct. + populate_song(read_buffer); + + free(song_size); free(read_buffer); + close(song_directory_descriptor); + close(song_binary_descriptor); } -void populate_array(int song_size, ssize_t read_buffer) { +/** + * Populates song holder with values from provided buffer. + */ +void populate_song(ssize_t song_buffer) { int index; int* int_buffer; int* int_pointer; @@ -230,15 +256,13 @@ void populate_array(int song_size, ssize_t read_buffer) { double* double_buffer; double* double_pointer; - // Check to make sure there are still open spots in songs_array. - if (song_index >= songs_array_max) { - resize_array(); + if (song_holder_struct != NULL ) { + free_song_holder(); } - - songs_array[song_index] = calloc(1, sizeof(songs_struct)); + song_holder_struct = calloc(1, sizeof(songs_struct)); // Get Song Name. - char_pointer = ((char*)read_buffer); + char_pointer = ((char*)song_buffer); char_buffer = calloc(1, BUFFER_SIZE); index = 0; while (char_pointer[0] != '\0') { @@ -246,7 +270,7 @@ void populate_array(int song_size, ssize_t read_buffer) { ++char_pointer; index++; } - songs_array[song_index]->song_name = copy_string(char_buffer); + song_holder_struct->song_name = copy_string(char_buffer); ++char_pointer; free(char_buffer); @@ -258,7 +282,7 @@ void populate_array(int song_size, ssize_t read_buffer) { ++char_pointer; index++; } - songs_array[song_index]->album_name = copy_string(char_buffer); + song_holder_struct->album_name = copy_string(char_buffer); ++char_pointer; free(char_buffer); @@ -270,7 +294,7 @@ void populate_array(int song_size, ssize_t read_buffer) { ++char_pointer; index++; } - songs_array[song_index]->artist = copy_string(char_buffer); + song_holder_struct->artist = copy_string(char_buffer); ++char_pointer; free(char_buffer); @@ -278,7 +302,7 @@ void populate_array(int song_size, ssize_t read_buffer) { float_buffer = calloc(1, (sizeof(float) + 1)); float_pointer = (float*)char_pointer; *float_buffer = *float_pointer; - songs_array[song_index]->duration = copy_float(float_buffer); + song_holder_struct->duration = copy_float(float_buffer); ++float_pointer; free(float_buffer); @@ -286,7 +310,7 @@ void populate_array(int song_size, ssize_t read_buffer) { double_buffer = calloc(1, (sizeof(double) + 1)); double_pointer = (double*)float_pointer; *double_buffer = *double_pointer; - songs_array[song_index]->hotttnesss = copy_double(double_buffer); + song_holder_struct->hotttnesss = copy_double(double_buffer); ++double_pointer; free(double_buffer); @@ -294,39 +318,53 @@ void populate_array(int song_size, ssize_t read_buffer) { int_buffer = calloc(1, (sizeof(int) + 1)); int_pointer = (int*)double_pointer; *int_buffer = *int_pointer; - songs_array[song_index]->year = copy_int(int_buffer); + song_holder_struct->year = copy_int(int_buffer); ++int_pointer; free(int_buffer); - - song_index++; } -/** - * Increase current buffer size and rebuffer songs array. - * Call to initialize, and then anytime the array runs out of space. - */ -void resize_array() { - songs_array_max = songs_array_max * 2; - - songs_array = realloc(songs_array, songs_array_max * sizeof(songs_struct* )); - if (songs_array != NULL) { - //write(1, "Allocation successful.\n", 24); - } else { - err_dump("Could not allocate memory for realloc."); +void get_song_count() { + int index = 0; + char* previous_name = calloc(1, BUFFER_SIZE); + char* previous_album = calloc(1, BUFFER_SIZE); + + previous_name[index] = '\n'; + previous_album[index] = '\n'; + + // Initialize to first song for start of while loop. + read_song_of_index(index); + + // Count current number of songs in array. + while ((strcmp(previous_name, song_holder_struct->song_name) != 0) && + (strcmp(previous_album, song_holder_struct->album_name) != 0)) { + free(previous_name); + free(previous_album); + previous_name = copy_string(song_holder_struct->song_name); + previous_album = copy_string(song_holder_struct->album_name); + + index++; + total_song_count++; + read_song_of_index(index); + printf("Total songs: %d\n", total_song_count); } + free(previous_name); + free(previous_album); } /** - * Prints all songs. + * Frees memory used by song holder. */ -void print_all_songs() { - int index = 0; - while (songs_array[index] != NULL) { - printf("Song #: %d\n", index); - print_song_info(songs_array[index]); - index++; +void free_song_holder() { + if (song_holder_struct != NULL) { + free(song_holder_struct->album_name); + free(song_holder_struct->artist); + free(song_holder_struct->song_name); + free(song_holder_struct->duration); + free(song_holder_struct->year); + free(song_holder_struct->hotttnesss); + free(song_holder_struct); } } @@ -334,32 +372,29 @@ void print_all_songs() { /** * Prints info of provided song. */ -void print_song_info(songs_struct* song) { - printf("Song Name: %s\n", song->song_name); - printf("Album Name: %s\n", song->album_name); - printf("Artist Name: %s\n", song->artist); - printf("Duration: %.2f\n", *song->duration); - printf("Year: %d\n", *song->year); - printf("Hotttnesss: %f\n", *song->hotttnesss); - printf("\n"); +void print_song_info() { + printf("Song Name: %s\n", song_holder_struct->song_name); + printf("Album Name: %s\n", song_holder_struct->album_name); + printf("Artist Name: %s\n", song_holder_struct->artist); + printf("Duration: %.2f\n", *song_holder_struct->duration); + printf("Year: %d\n", *song_holder_struct->year); + printf("Hotttnesss: %f\n", *song_holder_struct->hotttnesss); + printf("\n\n"); } + /** - * Finds and prints infor for song given index. + * Prints all songs. */ -void print_song_of_index(int index) { - if (songs_array[index] != NULL) { +void print_all_songs() { + int index = 0; + read_song_of_index(index); + while (index < total_song_count) { printf("Song #: %d\n", index); - printf("Song Name: %s\n", songs_array[index]->song_name); - printf("Album Name: %s\n", songs_array[index]->album_name); - printf("Artist Name: %s\n", songs_array[index]->artist); - printf("Duration: %.2f\n", *songs_array[index]->duration); - printf("Year: %d\n", *songs_array[index]->year); - printf("Hotttnesss: %f\n", *songs_array[index]->hotttnesss); - printf("\n"); - } else { // No song at provided index. - printf("No song at index %d\n", index); + print_song_info(); + index++; + read_song_of_index(index); } } @@ -376,33 +411,29 @@ void print_help_text() { } -/** - * Searches through array and finds song based on user input. - */ +// /** +// * Searches through array and finds song based on user input. +// */ void find_song(char* user_input_string) { - int song_counter = -1; // To account for arrays starting at 0. - int index = 0; char* temp_string; songs_struct* song; songs_struct* temp_song = calloc(1, sizeof(songs_struct*)); - // Count current number of songs in array. - while (songs_array[index] != NULL) { - song_counter++; - index++; + if (total_song_count < 1) { + get_song_count(); } - // Search for user's input, first by song_name, then by album name. - song = search_array_by_song(temp_song, 0, song_counter, user_input_string); + // // Search for user's input, first by song_name, then by album name. + song = search_array_by_song(temp_song, 0, total_song_count, user_input_string); // Check returned song. if (song != NULL) { - print_song_info(song); + print_song_info(); free(temp_song); } else { // Not found. Search again by album instead of song_name. - song = search_array_by_album(0, song_counter, user_input_string); + song = search_array_by_album(0, total_song_count, user_input_string); if (song != NULL) { - print_song_info(song); + print_song_info(); } else { // Could not find song or album. temp_string = first_letter_upper(user_input_string); @@ -427,11 +458,12 @@ songs_struct* search_array_by_song(songs_struct* return_song, if (first_index >= last_index) { // End of search. Handle accordingly. - temp_string = to_lower_case(songs_array[first_index]->song_name); + read_song_of_index(first_index); + temp_string = to_lower_case(song_holder_struct->song_name); if ((strcmp(desired_record, temp_string)) == 0 ) { // Match found. Use given struct. free(temp_string); - return_song = songs_array[first_index]; + return_song = song_holder_struct; } else { // End of search and no match found. Use NULL. free(temp_string); @@ -441,11 +473,12 @@ songs_struct* search_array_by_song(songs_struct* return_song, } else { // Still more values to search. Handle accordingly. int mid_index = (first_index + last_index) / 2; - temp_string = to_lower_case(songs_array[mid_index]->song_name); + read_song_of_index(mid_index); + temp_string = to_lower_case(song_holder_struct->song_name); if ((strcmp(desired_record, temp_string)) == 0 ) { // Match found. Use given struct. free(temp_string); - return_song = songs_array[mid_index]; + return_song = song_holder_struct; } else { if ((strcmp(desired_record, temp_string)) < 0 ) { // Current struct song name is higher letter than desired. @@ -474,11 +507,12 @@ songs_struct* search_array_by_song(songs_struct* return_song, songs_struct* search_array_by_album(int first_index, int last_index, char* desired_record) { int index = 0; - while (songs_array[index] != NULL) { - char* temp_string = to_lower_case(songs_array[index]->album_name); + while (index < total_song_count) { + read_song_of_index(index); + char* temp_string = to_lower_case(song_holder_struct->album_name); if (strcmp(temp_string, desired_record) == 0) { free(temp_string); - return songs_array[index]; + return song_holder_struct; } index++; free(temp_string); @@ -486,22 +520,3 @@ songs_struct* search_array_by_album(int first_index, int last_index, char* desir return NULL; } - - -/** - * Frees remaining memory and so program can close cleanly. - */ -void exit_program() { - int index = 0; - while (songs_array[index] != NULL) { - free(songs_array[index]->album_name); - free(songs_array[index]->artist); - free(songs_array[index]->song_name); - free(songs_array[index]->duration); - free(songs_array[index]->year); - free(songs_array[index]->hotttnesss); - free(songs_array[index]); - index++; - } - free(songs_array); -}