From 0c0d6e11ea3756bb4b63c63e2a635797ac0aeb1d Mon Sep 17 00:00:00 2001
From: Brandon Rodriguez <brodriguez8774@gmail.com>
Date: Fri, 22 Sep 2017 20:05:42 -0400
Subject: [PATCH] Add full read in of test file with valgrind errors corrected

---
 BuildDataBase.c | 160 ++++++++++++++++++++++++++++++++++++++++++------
 CopyFunctions.c |  80 ++++++++++++++++++++++++
 HelperHeader.h  |  18 ++++++
 makefile        |   2 +-
 4 files changed, 241 insertions(+), 19 deletions(-)
 create mode 100644 CopyFunctions.c
 create mode 100644 HelperHeader.h

diff --git a/BuildDataBase.c b/BuildDataBase.c
index a81702b..ebc3ef0 100644
--- a/BuildDataBase.c
+++ b/BuildDataBase.c
@@ -20,15 +20,13 @@
 
 
 // Import headers.
-//#include <string.h>
-//#include <stdlib.h>
-//#include <ctype.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include "apue.h"
+#include "HelperHeader.h"
 
 
 // Define Vars.
@@ -47,7 +45,7 @@ typedef struct {
 } songs_struct;                 // Songs struct.
 
 int songs_array_max = ARRAY_SIZE;  // Saves current size of songs array.
-int current_song = 0;           // Current song value to save.
+int song_index = 0;             // Current song index.
 songs_struct** songs_array;     // The array which holds all song pointers.
 
 
@@ -57,6 +55,10 @@ void read_file();               // Reads in chunk of file.
 void read_line();               // Separates file chunk into lines.
 void tokenize_line();           // Separates lines into fields.
 void populate_array();          // Populates array with fields.
+void resize_array();            // Reallocates memory for array.
+char* remove_quotes();          // Removes quotes from string value.
+void print_song_info();         // Prints all info for provided song.
+void exit_program();            // Frees memory and closes program.
 
 
 /**
@@ -64,8 +66,23 @@ void populate_array();          // Populates array with fields.
  * Initializes and runs program.
  */
 int main(int argc, char* argv[]) {
+    songs_array = calloc(songs_array_max, sizeof(songs_struct *));
     int file_descriptor = open_file();
     read_file(file_descriptor);
+    write(1, "\n\n\n\n\n", 10);
+    print_song_info(songs_array[1]);
+    print_song_info(songs_array[2]);
+    print_song_info(songs_array[3]);
+    print_song_info(songs_array[4]);
+    print_song_info(songs_array[5]);
+    print_song_info(songs_array[6]);
+    print_song_info(songs_array[7]);
+    print_song_info(songs_array[8]);
+    print_song_info(songs_array[9]);
+    print_song_info(songs_array[10]);
+
+
+    exit_program();
 }
 
 
@@ -108,8 +125,6 @@ void read_file(int file_descriptor) {
     *temp_buffer = *read_buffer;
     printf("Looping through buffer...\n");
     while (index > 0) {
-        //printf("%s", read_buffer);
-        //printf("%c", temp_buffer[index]);
         if (temp_buffer[index] == '\n') {
             // Found first null terminator. Save location and exit loop.
             offset_amount = index;
@@ -117,6 +132,7 @@ void read_file(int file_descriptor) {
         }
         index--;
     }
+    free(temp_buffer);
 
     // Set "Read Size" for lseek to travel to last null terminator.
     read_size = BUFFER_SIZE - offset_amount;
@@ -126,10 +142,8 @@ void read_file(int file_descriptor) {
     }
 
     printf("Buffer: %d, Offset: %d, ReadSize: %ld\n\n", BUFFER_SIZE, offset_amount, read_size);
-    //write(1, read_buffer, BUFFER_SIZE);
-    //write(1, read_buffer, read_size);
-    printf("\n\n");
     read_line(read_buffer, read_size);
+    free(read_buffer);
 }
 
 
@@ -164,7 +178,10 @@ void read_line(char *read_buffer, size_t read_size) {
             chunk_index++;
         }
     }
-    printf("\n");
+    // Last field so tokenize line one last time.
+    line_buffer[line_index] = '\0';
+    tokenize_line(line_buffer);
+    free(line_buffer);
 }
 
 
@@ -177,8 +194,8 @@ void tokenize_line(char *line_buffer) {
     int field_number = 0;
     char* field_buffer;
 
-    printf("\n\nTokenizing line...\n");
     field_buffer = calloc(BUFFER_SIZE, sizeof(char));
+    songs_array[song_index] = calloc(1, sizeof(songs_struct));
 
     while (strcmp(&line_buffer[line_index], "\0") != 0) {
         // Check for comma to denote next field.
@@ -187,30 +204,137 @@ void tokenize_line(char *line_buffer) {
             field_index = 0;
             line_index++;
 
-            if (strcmp(field_buffer, "") != 0) {
-                printf("%s\n", field_buffer);
+            //if (strcmp(field_buffer, "") != 0) {
                 populate_array(field_number, field_buffer);
                 field_number++;
-            }
+            //}
 
             free(field_buffer);
             field_buffer = calloc(BUFFER_SIZE, sizeof(char));
         } else {
             // No comma found.
             field_buffer[field_index] = line_buffer[line_index];
-            //printf("%c", line_buffer[line_index]);
-            //printf("%c", field_buffer[field_index]);
             field_index++;
             line_index++;
         }
     }
-    current_song++;
+    // Last field so populate values one last time.
+    populate_array(field_number, field_buffer);
+    song_index++;
+    free(field_buffer);
 }
 
 
 /**
  * Takes provided field value and associates with song in struct.
  */
-void populate_array(int field_number, char *field_value) {
+void populate_array(int field_number, char *field_buffer) {
+    int temp_int;
+    int* temp_int_ptr;
+    float temp_float;
+    float* temp_float_ptr;
+    double temp_double;
+    double* temp_double_ptr;
+
+    // Remove unecessary quotes from string value fields.
+    if (field_number == 3 || field_number == 8 || field_number == 17) {
+        field_buffer = remove_quotes(field_buffer);
+    }
+
+    // Go through provided field and assign values appropriately with switch.
+    switch(field_number) {
+        case 3: // Album name.
+            songs_array[song_index]->album_name = copy_string(field_buffer);
+            break;
+        case 8: // Artist name.
+            songs_array[song_index]->artist = copy_string(field_buffer);
+            break;
+        case 10: // Duration.
+            temp_float = atof(field_buffer);
+            temp_float_ptr = &temp_float;
+            songs_array[song_index]->duration = copy_float(temp_float_ptr);
+            break;
+        case 14: // Hotttness.
+            temp_double = atof(field_buffer);
+            // Check if NAN.
+            if (temp_double != temp_double) {
+                temp_double = 0;
+            }
+            temp_double_ptr = &temp_double;
+            songs_array[song_index]->hotttnesss = copy_double(temp_double_ptr);
+            break;
+        case 17: // Song name.
+            songs_array[song_index]->song_name = copy_string(field_buffer);
+            break;
+        case 18: // Year.
+            temp_int = atoi(field_buffer);
+            temp_int_ptr = &temp_int;
+            songs_array[song_index]->year = copy_int(temp_int_ptr);
+            break;
+        default:
+            // Do nothing. This is not a field we care about.
+            break;
+    }
+}
+
+
+/**
+ * Removes quotes from provided string.
+ */
+char* remove_quotes(char* a_string) {
+    size_t string_length = strlen(a_string);
+    int orig_index;
+    int replace_index = 0;
+
+    for (orig_index = 0; orig_index < string_length; orig_index++) {
+        if (a_string[orig_index] != '\"') {
+            a_string[replace_index] = a_string[orig_index];
+            replace_index++;
+        }
+    }
 
+    // Fill rest of values with null terminators.
+    while (replace_index < string_length) {
+        a_string[replace_index] = '\0';
+        replace_index++;
+    }
+
+    return a_string;
+}
+
+
+/**
+ * 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 hotness = *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", hotness);
+    printf("\n");
+}
+
+
+/**
+ * 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);
 }
diff --git a/CopyFunctions.c b/CopyFunctions.c
new file mode 100644
index 0000000..643ab82
--- /dev/null
+++ b/CopyFunctions.c
@@ -0,0 +1,80 @@
+/**
+ * Brandon Rodriguez
+ * CS 3240
+ * 09-19-17
+ */
+
+
+/**
+ * Helper functions to have consistent value copying and error handling.
+ *
+ * All functions use memcpy to copy data, and error.c's err_dump on failure.
+ *
+ * All functions require a "source" pointer of equivalent typing, and returns
+ * a pointer to copied item's location.
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include "apue.h"
+
+
+/**
+ * Copies string from destination to source.
+ */
+char* copy_string(char *source_ptr) {
+    char *copy_ptr;
+    copy_ptr = calloc((strlen(source_ptr) + 1), sizeof(char));
+    if (copy_ptr != NULL) {
+        memcpy(copy_ptr, source_ptr, ((strlen(source_ptr) + 1)  * sizeof(char)));
+    } else {
+        err_dump("Could not allocate memory for string calloc.");
+    }
+    return copy_ptr;
+}
+
+
+/**
+ * Copies float from destination to source.
+ */
+int* copy_int(int *source_ptr) {
+    int *copy_ptr;
+    copy_ptr = calloc(1, (sizeof(int) + 1));
+    if (copy_ptr != NULL) {
+        memcpy(copy_ptr, source_ptr, sizeof(int));
+    } else {
+        err_dump("Could not allocate memory for int calloc.");
+    }
+    return copy_ptr;
+}
+
+
+/**
+ * Copies float from destination to source.
+ */
+float* copy_float(float *source_ptr) {
+    float *copy_ptr;
+    copy_ptr = calloc(1, (sizeof(float) + 1));
+    if (copy_ptr != NULL) {
+        memcpy(copy_ptr, source_ptr, sizeof(float));
+    } else {
+        err_dump("Could not allocate memory for float calloc.");
+    }
+    return copy_ptr;
+}
+
+
+/**
+ * Copies double from destination to source.
+ */
+double* copy_double(double *source_ptr) {
+    double *copy_ptr;
+    copy_ptr = calloc(1, (sizeof(double) + 1));
+    if (copy_ptr != NULL) {
+        memcpy(copy_ptr, source_ptr, sizeof(double));
+    } else {
+        err_dump("Could not allocate memory for double calloc.");
+    }
+    return copy_ptr;
+}
diff --git a/HelperHeader.h b/HelperHeader.h
new file mode 100644
index 0000000..11f2fe6
--- /dev/null
+++ b/HelperHeader.h
@@ -0,0 +1,18 @@
+/**
+ * Brandon Rodriguez
+ * CS 3240
+ * 09-19-17
+ */
+
+
+/**
+ * A personal header for helper-functions.
+ */
+
+
+// Function prototypes.
+char* copy_string(char* source_ptr);
+int* copy_int(int* source_ptr);
+float* copy_float(float* source_ptr);
+double* copy_double(double* source_ptr);
+
diff --git a/makefile b/makefile
index 3b97d65..a8602f8 100644
--- a/makefile
+++ b/makefile
@@ -1,5 +1,5 @@
 all:
-	gcc -Wall -Wpedantic -std=c99 -g BuildDataBase.c error.c -o BuildDataBase
+	gcc -Wall -Wpedantic -std=c99 -g BuildDataBase.c error.c CopyFunctions.c -o BuildDataBase
 	gcc -Wall -Wpedantic -std=c99 -g UseDataBase.c -o UseDataBase
 build:
 	./BuildDataBase
-- 
GitLab