From 8cd1fc522a88560c4133361941a9e19565f74714 Mon Sep 17 00:00:00 2001
From: Brandon Rodriguez <brodriguez8774@gmail.com>
Date: Sun, 24 Sep 2017 22:29:57 -0400
Subject: [PATCH] Add (hopefully) finishing touches for program

Now reads from initial csv (both small test and full size)
Saves to binary file
Reads binary file and populates array
Lets user search through via both song name and album name
---
 BuildDataBase.c | 113 +++++++++++++++++++++++++++++-------------------
 UseDataBase.c   |  32 +++++++++++---
 2 files changed, 96 insertions(+), 49 deletions(-)

diff --git a/BuildDataBase.c b/BuildDataBase.c
index 75128b8..afb9222 100644
--- a/BuildDataBase.c
+++ b/BuildDataBase.c
@@ -44,10 +44,11 @@ typedef struct {
     double* hotttnesss;
 } songs_struct;                 // Songs struct.
 
-int test_file_bool = 1;         // Check if using smaller test csv or not.
+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.
+songs_struct** temp_array;      // The temp array for sorting.
 
 
 // Method Declaration.
@@ -59,7 +60,7 @@ void resize_array();            // Increase buffer size of song array.
 void populate_array();          // Populates array with fields.
 void print_all_songs();         // Prints info for all songs in array.
 void print_song_info();         // Prints all info for provided song.
-void sort_array();              // Sorts array by song name.
+void sort_array();              // Linearly sorts array by song name.
 void save_array();              // Saves entire array to file(s).
 void save_line();               // Creates/saves single line of song data.
 void write_song_field();        // Writes a single song_filed to file.
@@ -83,12 +84,13 @@ int main(int argc, char* argv[]) {
     }
 
     read_file(file_descriptor);
+    write(1, "Sorting arrays...\n", 19);
     sort_array();
     //print_all_songs();
     write(1, "Saving to file...\n", 19);
     save_array();
     write(1, "Finished.\n", 11);
-    write(1, "Closing program...\n", 19);
+    write(1, "Closing program...\n", 20);
     close(file_descriptor);
     exit_program();
 }
@@ -127,41 +129,63 @@ int open_file(char* file_location, int operator_flags) {
 void read_file(int file_descriptor) {
     char *read_buffer;
     char *temp_buffer;
+    int current_read_int = 0;
     int index;
     int offset_amount;
-    size_t read_size;
+    off_t read_value;
+    off_t offset_size;
 
     read_buffer = calloc(1, BUFFER_SIZE);
-    temp_buffer = calloc(1, BUFFER_SIZE);
 
-    off_t read_value = read(file_descriptor, read_buffer, BUFFER_SIZE);
-    if (read_value < 0) {
-        err_sys("Failed to read line.");
-    }
+    while ((read_value = read(file_descriptor, read_buffer, (BUFFER_SIZE - 1))) != 0) {
+        if (read_value < 0) {
+            err_sys("Failed to read line.");
+        }
 
-    // Start from end of buffer. Read backwards until first null terminator
-    // is found.
-    index = BUFFER_SIZE - 1;
-    offset_amount = 0;
-    *temp_buffer = *read_buffer;
-    while (index > 0) {
-        if (temp_buffer[index] == '\n') {
-            // Found first null terminator. Save location and exit loop.
-            offset_amount = index;
-            index = 0;
+        // Start from end of buffer. Read backwards until first null terminator
+        // is found.
+        index = BUFFER_SIZE - 1;
+        offset_amount = 0;
+        temp_buffer = read_buffer;
+        while (index > 0) {
+            if (temp_buffer[index] == '\n') {
+                // Found newline terminator. Save location and exit loop.
+                offset_amount = index;
+                index = 0; // To exit loop.
+            }
+            index--;
         }
-        index--;
-    }
-    free(temp_buffer);
 
-    // Set "Read Size" for lseek to travel to last null terminator.
-    read_size = BUFFER_SIZE - offset_amount;
-    off_t offset_size = lseek(file_descriptor, read_size, SEEK_CUR);
-    if (offset_size < 0) {
-        err_sys("Failed to update pointer on read in.");
-    }
+        // Rewind to start of current read, then go to actual read value
+        // of buffer after cutoff.
+        size_t actual_read_size = strlen(read_buffer);
+        if (actual_read_size != 4095) {
+            actual_read_size--;
+        }
+
+        offset_size = lseek(file_descriptor, (-(actual_read_size)), SEEK_CUR);
+        if (offset_size < 0) {
+            err_sys("Failed to update pointer on read in.");
+        }
+        offset_size = lseek(file_descriptor, offset_amount, SEEK_CUR);
+        if (offset_size < 0) {
+            err_sys("Failed to update pointer on read in.");
+        }
 
-    read_line(read_buffer, read_size);
+        // Remove "garbage" data at end of read and pass forward.
+        index = offset_amount + 1;
+        while (index < BUFFER_SIZE) {
+            read_buffer[index] = '\0';
+            index++;
+        }
+        read_line(read_buffer, offset_size);
+
+        // Reset read buffer for next read.
+        free(read_buffer);
+        read_buffer = calloc(1, BUFFER_SIZE);
+
+        current_read_int++;
+    }
     free(read_buffer);
 }
 
@@ -224,10 +248,8 @@ void tokenize_line(char *line_buffer) {
             field_index = 0;
             line_index++;
 
-            //if (strcmp(field_buffer, "") != 0) {
-                populate_array(field_number, field_buffer);
-                field_number++;
-            //}
+            populate_array(field_number, field_buffer);
+            field_number++;
 
             free(field_buffer);
             field_buffer = calloc(1, BUFFER_SIZE);
@@ -254,7 +276,7 @@ void resize_array() {
 
     songs_array = realloc(songs_array, songs_array_max * sizeof(songs_struct* ));
     if (songs_array != NULL) {
-        printf("Allocation successful.\n");
+        //write(1, "Allocation successful.\n", 24);
     } else {
         err_dump("Could not allocate memory for realloc.");
     }
@@ -281,14 +303,17 @@ void populate_array(int field_number, char *field_buffer) {
     switch(field_number) {
         case 3: // Album name.
             songs_array[song_index]->album_name = copy_string(field_buffer);
+            //printf("Album: %s\n", songs_array[song_index]->album_name);
             break;
         case 8: // Artist name.
             songs_array[song_index]->artist = copy_string(field_buffer);
+            //printf("Artist: %s\n", songs_array[song_index]->artist);
             break;
         case 10: // Duration.
             temp_float = atof(field_buffer);
             temp_float_ptr = &temp_float;
             songs_array[song_index]->duration = copy_float(temp_float_ptr);
+            //printf("Duration: %.2f\n", *songs_array[song_index]->duration);
             break;
         case 14: // Hotttnesss.
             temp_double = atof(field_buffer);
@@ -298,14 +323,17 @@ void populate_array(int field_number, char *field_buffer) {
             }
             temp_double_ptr = &temp_double;
             songs_array[song_index]->hotttnesss = copy_double(temp_double_ptr);
+            //printf("Hotttnesss: %.2f\n", *songs_array[song_index]->hotttnesss);
             break;
         case 17: // Song name.
             songs_array[song_index]->song_name = copy_string(field_buffer);
+            //printf("Name: %s\n", songs_array[song_index]->song_name);
             break;
         case 18: // Year.
             temp_int = atoi(field_buffer);
             temp_int_ptr = &temp_int;
             songs_array[song_index]->year = copy_int(temp_int_ptr);
+            //printf("Year: %d\n", *songs_array[song_index]->year);
             break;
         default:
             // Do nothing. This is not a field we care about.
@@ -315,7 +343,7 @@ void populate_array(int field_number, char *field_buffer) {
 
 
 /**
- * Sorts array by song name.
+ * Uses linear sort to arrange array by song name.
  */
 void sort_array() {
     int sorted_bool = 0;    // Holds if array has been sorted during this call.
@@ -324,7 +352,7 @@ void sort_array() {
 
     // Loop through all array elements and sort if necessary.
     // Starts at 1 due to comparing two elements at once.
-    while (songs_array[index] != NULL) {
+    while ((songs_array[index] != NULL) &&(songs_array[index]->song_name != NULL)) {
         if (strcmp(songs_array[index - 1]->song_name, songs_array[index]->song_name) > 0) {
             temp_song = songs_array[index - 1];
             songs_array[index - 1] = songs_array[index];
@@ -356,16 +384,12 @@ void print_all_songs() {
  * Attempts to find song with provided name. Prints result.
  */
 void print_song_info(songs_struct* song) {
-    float duration = *song->duration;
-    int year = *song->year;
-    double hotttnesss = *song->hotttnesss;
-
     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", duration);
-    printf("Year: %d\n", year);
-    printf("Hotttnesss: %f\n", hotttnesss);
+    printf("Duration: %.2f\n", *song->duration);
+    printf("Year: %d\n", *song->year);
+    printf("Hotttnesss: %f\n", *song->hotttnesss);
     printf("\n");
 }
 
@@ -377,6 +401,7 @@ void save_array() {
     int song_directory_descriptor;
     int song_binary_descriptor;
 
+
     // Check test csv bool. If true, write to smaller csv.
     if (test_file_bool) {
         song_directory_descriptor = open_file("Data/SongDirectory_Small", O_CREAT | O_TRUNC | O_WRONLY);
@@ -385,8 +410,8 @@ void save_array() {
         song_directory_descriptor = open_file("Data/SongDirectory", O_CREAT | O_TRUNC | O_WRONLY);
         song_binary_descriptor = open_file("Data/BinarySongData", O_CREAT | O_TRUNC | O_WRONLY);
     }
-    song_index = 0;
 
+    song_index = 0;
     while (songs_array[song_index] != NULL) {
         save_line(song_directory_descriptor, song_binary_descriptor);
         song_index++;
diff --git a/UseDataBase.c b/UseDataBase.c
index 2470cf6..4c0812c 100644
--- a/UseDataBase.c
+++ b/UseDataBase.c
@@ -46,7 +46,7 @@ typedef struct {
     double* hotttnesss;
 } songs_struct;                 // Songs struct.
 
-int test_file_bool = 1;         // Check if using smaller test csv or not.
+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.
@@ -56,7 +56,7 @@ songs_struct** songs_array;     // The array which holds all song pointers.
 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();            // Reallocates memory for array.
+void resize_array();            // Increase buffer size of song array.
 void print_all_songs();         // Prints info for all songs in array.
 void print_song_info();         // Prints all info for provided song.
 void print_help_text();         // Prints helper text for user.
@@ -110,18 +110,22 @@ int main(int argc, char* argv[]) {
 
     print_help_text();
 
+    // Actually run program for user input.
     while (run_program_bool) {
         user_input_string = calloc(1, BUFFER_SIZE);
 
         // Read input from console.
         write(1, "Enter input: ", 14);
         read_value = read(0, user_input_string, BUFFER_SIZE);
+        if (read_value < 0) {
+            err_sys("Failed to read line.");
+        }
         write(1, "\n", 2);
 
         user_input_string = remove_newline(user_input_string);
 
         // Read user input and handle accordingly.
-        if ((user_input_string != NULL) && (strcmp(user_input_string, "") != 0)) {
+        if ((user_input_string != NULL)) { // && (strcmp(user_input_string, "") != 0)) {
             input_to_lower = to_lower_case(user_input_string);
 
             // Check if user needs reprinting of help text.
@@ -138,7 +142,6 @@ int main(int argc, char* argv[]) {
                 print_all_songs();
             }
             else { // Attempt to find song with given name.
-                //printf("User Input: %s", input_to_lower);
                 find_song(input_to_lower);
             }
             free(input_to_lower);
@@ -201,6 +204,11 @@ 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();
+    }
+
     songs_array[song_index] = calloc(1, sizeof(songs_struct));
 
     // Get Song Name.
@@ -265,10 +273,24 @@ void populate_array(int song_size, ssize_t read_buffer) {
     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.");
+    }
+}
+
 
 /**
  * Prints all songs.
-- 
GitLab