9511_project03

Command line program that parses a bank .csv file and generates and output file in format .csv or .xml containing the debits and credits of every user.
Index Commits Files Refs README LICENSE
commit 95ef9920529da0a2511562604ff2b1813601259b
parent e89839f281cac8a05411172f4294b3e714e6377d
Author: klewer-martin <martin.cachari@gmail.com>
Date:   Thu,  5 Aug 2021 19:15:14 -0300

New function to load users to the vector

Diffstat:
MMakefile | 2+-
Minclude/user.h | 3++-
Minclude/utils.h | 6+++++-
Minclude/vector.h | 11+++++++----
Msource/main.c | 136++-----------------------------------------------------------------------------
Msource/user.c | 13++++++++++++-
Msource/utils.c | 129+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
7 files changed, 153 insertions(+), 147 deletions(-)
diff --git a/Makefile b/Makefile
@@ -21,7 +21,7 @@ vector.o: $(HFOLDER)/vector.h $(HFOLDER)/status.h
 status.o: $(HFOLDER)/status.h
     $(CC) $(CFLAGS) -c $(SRCFOLDER)/status.c
 
-utils.o: $(HFOLDER)/status.h $(HFOLDER)/user.h
+utils.o: $(HFOLDER)/status.h $(HFOLDER)/user.h $(HFOLDER)/vector.h
     $(CC) $(CFLAGS) -c $(SRCFOLDER)/utils.c
 
 user.o: $(HFOLDER)/status.h $(HFOLDER)/user.h
diff --git a/include/user.h b/include/user.h
@@ -15,7 +15,8 @@ typedef struct {
 
 status_t user_create(ADT_user_t **);
 status_t user_destroy(ADT_user_t **);
-status_t user_set_data(ADT_user_t *, char **);
+status_t user_set_data_from_str(ADT_user_t *, char **);
+status_t user_set_data(ADT_user_t *, ulong, ulong, ulong);
 status_t user_add_amount(ADT_user_t *, long);
 
 int user_equals(const void *, const void *);
diff --git a/include/utils.h b/include/utils.h
@@ -9,6 +9,7 @@
 #include "cla.h"
 #include "user.h"
 #include "status.h"
+#include "vector.h"
 
 #define _XOPEN_SOURCE
 #define __USE_XOPEN
@@ -31,9 +32,12 @@
 #define XML_STR_CREDIT    "credits"
 #define XML_STR_DEBIT    "debits"
 
-status_t get_date(time_t *, char **);
+status_t get_date(time_t *, char *);
+
 status_t array_destroy(char **, size_t);
+
 status_t string_split(char *, char **, char *);
+status_t load_users_to_vector(ADT_Vector_t **, ADT_cla_t *);
 
 bool is_valid_card(char *);
 
diff --git a/include/vector.h b/include/vector.h
@@ -1,14 +1,17 @@
 #ifndef VECTOR__H
 #define VECTOR__H
 
-#define VECTOR_INIT_SIZE        10
-#define VECTOR_GROWTH_FACTOR    2
-
 #include <stdlib.h>
 
-#include "utils.h"
 #include "status.h"
 
+#define VECTOR_INIT_SIZE        10
+#define VECTOR_GROWTH_FACTOR    2
+
+#define XML_STR_HEADER    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+#define XML_STR_ROOT    "root"
+#define XML_STR_ROW        "row"
+
 typedef status_t (*printer_t)(const void *, FILE *);
 typedef int (*comparator_t)(const void *, const void *);
 
diff --git a/source/main.c b/source/main.c
@@ -9,12 +9,6 @@ int main (int argc, char *argv[])
     status_t st;
     cla_t cla;
     ADT_Vector_t *v;
-    ADT_user_t *user, *user_tmp;
-    char buffer[IN_FILE_MAX_LEN];
-    char *endptr, **data;
-    size_t i;
-    long amount;
-    time_t epoch;
 
     /* Asigna memoria a cla (c.l.a.: "command line arguments") */
     if((st = cla_create(&cla)) != OK) {
@@ -36,162 +30,43 @@ int main (int argc, char *argv[])
         return st;
     }
 
-    /* Crea un arreglo de cadenas de caracteres */
-    if((data = malloc(sizeof(char *) * IN_FILE_FIELDS)) == NULL) {
-        show_status(ERROR_MEMORY);
-        cla_destroy(cla);
-        ADT_Vector_destroy(&v);
-        return ERROR_MEMORY;
-    }
-
-    for(i = 0; i < IN_FILE_FIELDS; i++) {
-        if((data[i] = calloc(sizeof(char), IN_FILE_FIELDS_MAX_LEN)) == NULL) {
-            show_status(ERROR_MEMORY);
-            cla_destroy(cla);
-            ADT_Vector_destroy(&v);
-            array_destroy(data, IN_FILE_FIELDS);
-            return ERROR_MEMORY;
-        }
-    }
-
     /* Setea el comparador a ADT_Vector */    
     if((st = ADT_Vector_set_comparator(v, user_equals)) != OK) {
         show_status(st);
         cla_destroy(cla);
         ADT_Vector_destroy(&v);
-        array_destroy(data, IN_FILE_FIELDS);
         return st;
     }
 
-    /* Crea un usuario temporal */
-    if((st = user_create(&user_tmp)) != OK) {
+    /* Carga el vector con los usuarios del archivo de entrada */
+    if((st = load_users_to_vector(&v, cla)) != OK) {
         show_status(st);
         cla_destroy(cla);
         ADT_Vector_destroy(&v);
-        array_destroy(data, IN_FILE_FIELDS);
         return st;
     }
 
-    /* Lee linea por linea del archivo de entrada */
-    while(fgets(buffer, IN_FILE_MAX_LEN, cla->fi)) {
-
-        /* Separa la linea leida segun un caracter delimitador */
-        if((st = string_split(buffer, data, IN_FILE_DELIM)) != OK) {
-            show_status(st);
-            cla_destroy(cla);
-            ADT_Vector_destroy(&v);
-            array_destroy(data, IN_FILE_FIELDS);
-            free(user_tmp);
-            return st;
-        }
-
-        /* Setea el usuario temporal con los datos obtenidos de la linea */
-        if((st = user_set_data(user_tmp, data)) != OK) {
-            show_status(st);
-            cla_destroy(cla);
-            ADT_Vector_destroy(&v);
-            array_destroy(data, IN_FILE_FIELDS);
-            free(user_tmp);
-            return st;
-        }
-
-        amount = strtol(data[POS_AMOUNT], &endptr, 10);
-        if(*endptr != '\0') {
-            show_status(st);
-            cla_destroy(cla);
-            ADT_Vector_destroy(&v);
-            array_destroy(data, IN_FILE_FIELDS);
-            free(user_tmp);
-            return ERROR_CORRUPT_DATA;
-        }
-
-        /* Transforma el tiempo de la linea leida a formato UNIX */
-        get_date(&epoch, data);
-
-        /* Comprueba que el tiempo de la linea leida no supere los argumentos ingresados */
-        if(epoch < cla->ti) continue;
-        else if(epoch > cla->tf) break;
-
-        /* Solo imprime en el archivo de salida las transacciones realizadas con una tarjeta valida */
-        if(!is_valid_card(data[POS_CARD_NUMBER])) {
-            fprintf(stderr, "%s: %s\n",STR_INVALID_CARD_NUMBER, data[POS_CARD_NUMBER]);
-            continue;
-        }
-
-        /* Busca el id del usuario en el vector */
-        if((user = ADT_Vector_get_elem(v, user_tmp)) != NULL) {
-            /* Si lo encuentra le suma el monto correspondiente */
-            if((st = user_add_amount(user, amount)) != OK) {
-                show_status(st);
-                cla_destroy(cla);
-                ADT_Vector_destroy(&v);
-                array_destroy(data, IN_FILE_FIELDS);
-                free(user_tmp);
-                return st;
-            }
-        }
-
-        /* Si no lo encuentra crea un usuario nuevo */
-        else { 
-            if((st = user_create(&user)) != OK) {
-                show_status(st);
-                cla_destroy(cla);
-                ADT_Vector_destroy(&v);
-                array_destroy(data, IN_FILE_FIELDS);
-                free(user_tmp);
-                return st;
-            }
-
-            if((st = user_set_data(user, data))) {
-                show_status(st);
-                cla_destroy(cla);
-                ADT_Vector_destroy(&v);
-                array_destroy(data, IN_FILE_FIELDS);
-                free(user_tmp);
-                return st;
-            }
-
-            /* Y lo agrega al vector */
-            if((st = ADT_Vector_add(&v, user)) != OK){
-                show_status(st);
-                free(user_tmp);
-                cla_destroy(cla);
-                ADT_Vector_destroy(&v);
-                array_destroy(data, IN_FILE_FIELDS);
-                free(user_tmp);
-                return st;
-            }
-        }
-        clean_buffer(buffer);
-        clean_array(data);
-    } /* End while */
-
     /* Ordena el vector con los usuarios */
     if((st = ADT_Vector_sort(v, user_comparator_credits_maxmin)) != OK) {
         show_status(st);
-        free(user_tmp);
         cla_destroy(cla);
         ADT_Vector_destroy(&v);
-        array_destroy(data, IN_FILE_FIELDS);
         return st;
     }
 
-    /* Setea el impresor a ADT_Vector */
+    /* Setea el impresor e imprime ADT_Vector segĂșn el argumento ingresado */
     if(!strcmp(cla->fmt, STR_FMT_CSV)) {
         if((st = ADT_Vector_set_printer(v, user_print_as_csv)) != OK) {
             show_status(st);
             cla_destroy(cla);
             ADT_Vector_destroy(&v);
-            array_destroy(data, IN_FILE_FIELDS);
             return st;
         }
         /* E imprime el vector con los usuarios */
         if((st = ADT_Vector_export_as_csv(v, cla->fo)) != OK) {
             show_status(st);
-            free(user_tmp);
             cla_destroy(cla);
             ADT_Vector_destroy(&v);
-            array_destroy(data, IN_FILE_FIELDS);
             return st;
         }
     }
@@ -200,22 +75,17 @@ int main (int argc, char *argv[])
             show_status(st);
             cla_destroy(cla);
             ADT_Vector_destroy(&v);
-            array_destroy(data, IN_FILE_FIELDS);
             return st;
         }
         if((st = ADT_Vector_export_as_xml(v, cla->fo)) != OK) {
             show_status(st);
-            free(user_tmp);
             cla_destroy(cla);
             ADT_Vector_destroy(&v);
-            array_destroy(data, IN_FILE_FIELDS);
             return st;
         }
     }
 
-    free(user_tmp);
     cla_destroy(cla);
     ADT_Vector_destroy(&v);
-    array_destroy(data, IN_FILE_FIELDS);
     return OK;
 }
diff --git a/source/user.c b/source/user.c
@@ -22,7 +22,7 @@ status_t user_destroy(ADT_user_t **user)
     return OK;
 }
 
-status_t user_set_data(ADT_user_t *user, char **data) 
+status_t user_set_data_from_str(ADT_user_t *user, char **data) 
 {
     char *endptr;
     long amount;
@@ -41,6 +41,17 @@ status_t user_set_data(ADT_user_t *user, char **data)
     return OK;
 }
 
+status_t user_set_data(ADT_user_t *user, ulong id, ulong c, ulong d) 
+{
+    if(user == NULL) return ERROR_NULL_POINTER;
+
+    user->id = id;
+    user->c = c;
+    user->d = d;
+
+    return OK;
+}
+
 status_t user_add_amount(ADT_user_t *user, long amount)
 {
     if(user == NULL) return ERROR_NULL_POINTER;
diff --git a/source/utils.c b/source/utils.c
@@ -51,26 +51,26 @@ status_t array_destroy(char **data, size_t fields)
     return OK;
 }
 
-status_t get_date(time_t *e, char **data)
+status_t get_date(time_t *e, char *str)
 {
     struct tm tm;
 
-    if(e == NULL || data == NULL) return ERROR_NULL_POINTER;
+    if(e == NULL || str == NULL) return ERROR_NULL_POINTER;
 
     /* Desactiva el horario de verano */
     tm.tm_isdst = 0;
 
-    switch(data[POS_TXN_DATE][2]) {
+    switch(str[2]) {
         case '/': 
-            strptime(data[2], "%d/%m/%Y %H:%M:%S", &tm);
+            strptime(str, "%d/%m/%Y %H:%M:%S", &tm);
             *e = mktime(&tm);
             break;
         case '-':
-            strptime(data[2], "%d-%m-%Y %H:%M:%S", &tm);
+            strptime(str, "%d-%m-%Y %H:%M:%S", &tm);
             *e = mktime(&tm);
             break;
         case '.':
-            strptime(data[2], "%d.%m.%Y %H:%M:%S", &tm);
+            strptime(str, "%d.%m.%Y %H:%M:%S", &tm);
             *e = mktime(&tm);
             break;
 
@@ -104,3 +104,120 @@ bool is_valid_card(char *card_no)
 
     return (sum % 10) ? false : true;
 }
+
+status_t load_users_to_vector(ADT_Vector_t **v, ADT_cla_t *cla)
+{
+    status_t st;
+    char buffer[IN_FILE_MAX_LEN];
+    char *endptr, **data;
+    ADT_user_t *user, *user_tmp;
+    time_t epoch;
+    long long amount;
+    ulong id, c, d;
+    size_t i;
+
+    if(v == NULL || cla == NULL) return ERROR_NULL_POINTER;
+    /* Asigna memoria a data */
+    if((data = malloc(sizeof(char *) * IN_FILE_FIELDS)) == NULL)
+        return ERROR_MEMORY;
+
+    for(i = 0; i < IN_FILE_FIELDS; i++) {
+        if((data[i] = calloc(sizeof(char), IN_FILE_FIELDS_MAX_LEN)) == NULL) {
+            array_destroy(data, IN_FILE_FIELDS);
+            return ERROR_MEMORY;
+        }
+    }
+
+    /* Crea un usuario temporal */
+    if((st = user_create(&user_tmp)) != OK) {
+        array_destroy(data, IN_FILE_FIELDS);
+        return st;
+    }
+
+    while(fgets(buffer, IN_FILE_MAX_LEN, cla->fi)) {
+        if((st = string_split(buffer, data, IN_FILE_DELIM)) != OK) {
+            free(user_tmp);
+            array_destroy(data, IN_FILE_FIELDS);
+            return st;
+        }
+
+        id = strtol(data[POS_USER_ID], &endptr, 10);
+        if(*endptr != '\0') {
+            free(user_tmp);
+            array_destroy(data, IN_FILE_FIELDS);
+            return ERROR_CORRUPT_DATA;
+        }
+
+        amount = strtol(data[POS_AMOUNT], &endptr, 10);
+        if(*endptr != '\0') {
+            free(user_tmp);
+            array_destroy(data, IN_FILE_FIELDS);
+            return ERROR_CORRUPT_DATA;
+        }
+
+        if(amount > 0) { c = amount; d = 0; }
+        else if(amount < 0) { c = 0; d = -amount; }
+
+        if((st = user_set_data(user_tmp, id, c, d)) != OK) {
+            free(user_tmp);
+            array_destroy(data, IN_FILE_FIELDS);
+            return ERROR_CORRUPT_DATA;
+        }
+
+        if((st = get_date(&epoch, data[POS_TXN_DATE])) != OK){
+            free(user_tmp);
+            array_destroy(data, IN_FILE_FIELDS);
+            return ERROR_CORRUPT_DATA;
+        }
+
+        /* Comprueba el que el tiempo este dentro de los valores pasados como argumentos */
+        if(epoch < cla->ti) continue;
+        else if(epoch > cla->tf) break;
+
+        /* Comprueba que la tarjeta usada en la transaccion sea la correcta */
+        if(!is_valid_card(data[POS_CARD_NUMBER])) {
+            fprintf(stderr, "%s: %s\n",STR_INVALID_CARD_NUMBER, data[POS_CARD_NUMBER]);
+            continue;
+        }
+
+        /* Busca el id del usuario en el vector */
+        if((user = ADT_Vector_get_elem(*v, user_tmp)) != NULL) {
+            /* Si lo encuentra le suma el monto correspondiente */
+            if((st = user_add_amount(user, amount)) != OK) {
+                array_destroy(data, IN_FILE_FIELDS);
+                free(user_tmp);
+                return st;
+            }
+        }
+
+        /* Si no lo encuentra crea un usuario nuevo */
+        else { 
+            if((st = user_create(&user)) != OK) {
+                array_destroy(data, IN_FILE_FIELDS);
+                free(user_tmp);
+                return st;
+            }
+
+            if((st = user_set_data(user, id, c, d))) {
+                array_destroy(data, IN_FILE_FIELDS);
+                free(user_tmp);
+                return st;
+            }
+
+            /* Y lo agrega al vector */
+            if((st = ADT_Vector_add(v, user)) != OK){
+                array_destroy(data, IN_FILE_FIELDS);
+                free(user_tmp);
+                return st;
+            }
+        }
+        clean_buffer(buffer);
+        clean_array(data);
+    } /* End while */
+
+        
+    array_destroy(data, IN_FILE_FIELDS);
+    free(user_tmp);
+
+    return OK;
+}