#include "easycsv_p.h" #include "easycsv_error.h" /*** Constructors ***/ easycsv* easycsv_init(const char *fp, EASYCSV_MODE mode) { easycsv *csv = NULL; int csv_exist = -1; csv = malloc(sizeof(easycsv)); if (csv == NULL) { easycsv_error(EASYCSV_MEMALLOC, NULL); return NULL; } memset(csv, 0, sizeof(easycsv)); csv->mode = mode; csv->file = NULL; csv->temp = NULL; strcpy(csv->fp, fp); csv->rows = 0; csv->cols = 0; csv_exist = !access(csv->fp, F_OK); /* Open file according to mode */ switch (csv->mode) { case EASYCSV_R: if (csv_exist) { csv->file = fopen(csv->fp, "r"); } else { easycsv_error(EASYCSV_EMPTYCSV, NULL); easycsv_free(csv); return NULL; } break; case EASYCSV_W: if (csv_exist) { csv->file = fopen(csv->fp, "r+"); } else { csv->file = fopen(csv->fp, "w"); } break; default: easycsv_error(EASYCSV_UNKNOWNIOMODE, NULL); easycsv_free(csv); return NULL; } if (csv->file == NULL) { easycsv_error(EASYCSV_OPENFAIL, NULL); easycsv_free(csv); return NULL; } /* Calculate rows and cols if file exists */ if (csv_exist) { csv->rows = easycsv_rows(csv); csv->cols = easycsv_columns(csv); } if (mode == EASYCSV_W) { csv->temp = tmpfile(); if (csv->temp == NULL) { easycsv_error(EASYCSV_OPENFAIL, NULL); easycsv_free(csv); return NULL; } } return csv; } void easycsv_free(easycsv *csv) { if (csv != NULL) { if (csv->file != NULL) fclose(csv->file); if (csv->temp != NULL) fclose(csv->temp); free(csv); } } /*** Acces, find ***/ int easycsv_find_value(const easycsv* csv, const char* value, unsigned int* col, unsigned int* row) { char *str; const unsigned int cols = easycsv_print_columns(csv); const unsigned int rows = easycsv_print_rows(csv); for (unsigned int row_l = 1; row_l <= rows; row_l++) { for (unsigned int col_l = 1; col_l <= cols; col_l++) { str = easycsv_read_value(csv, col_l, row_l); if (strcmp(str, value) == 0) { *col = col_l; *row = row_l; free(str); return 0; } free(str); } } easycsv_error(EASYCSV_FINDVALUEFAIL, value); return -1; } int easycsv_find_num_value(const easycsv* csv, const char* value) { char *str; int num = 0; const unsigned int cols = easycsv_print_columns(csv); const unsigned int rows = easycsv_print_rows(csv); for (unsigned int row_l = 1; row_l <= rows; row_l++) { for (unsigned int col_l = 1; col_l < cols; col_l++) { str = easycsv_read_value(csv, col_l, row_l); if (strcmp(str, value) == 0) { num++; } free(str); } } return num; } /*** Acces, read ***/ char* easycsv_read_value(const easycsv *csv, unsigned int col, unsigned int row) { char str_row[BUFSIZ]; size_t st; char *pch, *val; if (row == 0) { easycsv_error(EASYCSV_ZEROROW, NULL); return NULL; } if (row > easycsv_print_rows(csv)) { easycsv_error(EASYCSV_ROWNOTEXIST, NULL); return NULL; } if (col == 0) { easycsv_error(EASYCSV_ZEROCOL, NULL); return NULL; } if (col > easycsv_print_columns(csv)) { easycsv_error(EASYCSV_COLNOTEXIST, NULL); return NULL; } /* Set file pointer to start */ easycsv_rewind(csv); for (unsigned int i = 1; i < row; i++) { fscanf(csv->file, "%*[^\n]\n", NULL); } fscanf(csv->file, "%s\n", str_row); /* Get first occurance of comma in str, the first value is ommited but not the comma */ pch = str_row; /* Repeat until desired col is found */ for (unsigned int i = 1; i < col; i++) { pch = strpbrk(pch + 1, ","); } val = malloc(BUFSIZ); if (pch == NULL) { st = 0; } else { /* Get span from start of string to first occurence of comma */ if (col > 1) pch++; st = strcspn(pch, ","); // If 0, no string exists! if (st > 0) { strncpy(val, pch, st + 1); } } val[st] = '\0'; return val; } /* char* */ /* easycsv_readcolumnvalue(const easycsv *csv, */ /* const char *col, */ /* const unsigned int row) */ /* { */ /* /\* ARGS CHECK *\/ */ /* if (_easycsv_checkcsvandstring_one(csv->csv, col) < 0) */ /* return NULL; */ /* if (row > csv->csv->rows) { */ /* _easycsv_printerror(csv->csv, EASYCSV_OVERMAXROW); */ /* return NULL; */ /* } */ /* /\* END ARGS CHECK *\/ */ /* int i = _easycsv_getcolumn(csv->csv, col); */ /* if (i < 1) { */ /* _easycsv_printerror(csv->csv, EASYCSV_COLNUMFAIL); */ /* return NULL; */ /* } */ /* return easycsv_readvalue(csv, i, row); */ /* } */ /*** Acces, print ***/ int easycsv_print_rows(const easycsv *csv) { if (csv != NULL) { return csv->rows; } else { return -1; } } int easycsv_print_columns(const easycsv *csv) { if (csv != NULL) { return csv->cols; } else { return -1; } } /*** Modifications, sort ***/ /*** Modifications, insert ***/ /* int */ /* easycsv_insertvalue(easycsv *csv, */ /* const char *val, */ /* const unsigned int col, */ /* const unsigned int row) */ /* { */ /* return easycsv_insertvaluemode(csv, val, col, row, EASYCSV_REPLACE); */ /* } */ /* int */ /* easycsv_insertvaluemode(easycsv *csv, */ /* const char *val, */ /* const unsigned int col, */ /* const unsigned int row, */ /* const EASYCSV_VALMODE valmode) */ /* { */ /* /\* ARGS CHECK *\/ */ /* if (_easycsv_checkcsvandstring_one(csv->csv, val) < 0) */ /* return -1; */ /* if (col == 0) { */ /* _easycsv_printerror(csv->csv, EASYCSV_ZEROCOL); */ /* return -1; */ /* } */ /* if (row == 0) { */ /* _easycsv_printerror(csv->csv, EASYCSV_ZEROROW); */ /* return -1; */ /* } */ /* /\* END ARGS CHECK *\/ */ /* /\* row extends max *\/ */ /* if (row > csv->csv->rows) { */ /* } */ /* char *rowstr = _easycsv_getrow(csv->csv, row); */ /* if (rowstr == NULL) */ /* return -1; */ /* size_t rowstrst = strlen(rowstr); */ /* size_t st = 0; */ /* size_t commas = 0; */ /* char *pch = NULL; */ /* char *newstr = NULL; */ /* /\* column is within limit *\/ */ /* if (col <= csv->csv->cols) { */ /* /\* Set pch to start of value in rowstr *\/ */ /* pch = _easycsv_setcharptovalue(csv->csv, rowstr, col); */ /* if (pch == NULL) */ /* return -1; */ /* /\* Calculate size of existing value *\/ */ /* st = strcspn(pch, ","); */ /* newstr = malloc(rowstrst - st + strlen(val) + 1); */ /* /\* Copy char to newstr before value (pch) *\/ */ /* strncpy(newstr, rowstr, pch - rowstr); */ /* /\* Insert value *\/ */ /* if (st != 0) { /\* Occupied cell *\/ */ /* switch (valmode) { */ /* case EASYCSV_CONCAT: { */ /* strncat(newstr, pch, st); */ /* strcat(newstr, val); */ /* break; */ /* } */ /* case EASYCSV_RCONCAT: { */ /* strcat(newstr, val); */ /* strncat(newstr, pch, st); */ /* break; */ /* } */ /* case EASYCSV_REPLACE: */ /* default: { */ /* strcat(newstr, val); */ /* break; */ /* } */ /* } */ /* } */ /* else { /\* Empty cell *\/ */ /* strcat(newstr, val); */ /* } */ /* /\* Set pch to after value *\/ */ /* pch = strchr(rowstr, ','); */ /* /\* Calculate length of rest of string *\/ */ /* st = strlen(pch); */ /* /\* Concentate rest of string including NULL char *\/ */ /* strcat(newstr, pch); */ /* } */ /* else { */ /* commas = col - csv->csv->cols; */ /* csv->csv->cols = col; */ /* newstr = malloc(rowstrst + commas + strlen(val) + 1); */ /* strncpy(newstr, rowstr, rowstrst); */ /* for (size_t i = 0; i < commas; i++) */ /* strncat(newstr, ",", 1); */ /* strcat(newstr, val); // append \0 */ /* } */ /* /\* UPDATE CSV *\/ */ /* char *str = NULL; */ /* /\* Row within limits *\/ */ /* if (row <= csv->csv->rows) { */ /* /\* Copy rows before newstr in csv to temp *\/ */ /* for (unsigned int i = 1; i < row; i++) { */ /* str = _easycsv_getrow(csv->csv, i); */ /* if (col > csv->csv->cols) { */ /* str = realloc(str, strlen(str) + commas + 1); */ /* for (size_t j = 0; j < commas; j++) { */ /* strncat(str, ",", 1); */ /* } */ /* } */ /* fputs(str, csv->csv->temp); */ /* free(str); */ /* } */ /* /\* Print newstr into temp *\/ */ /* fputs(newstr, csv->csv->temp); */ /* /\* Copy the rest of rows *\/ */ /* for (unsigned int i = row + 1; i <= csv->csv->rows; i++) { */ /* str = _easycsv_getrow(csv, i); */ /* if (col > csv->csv->cols) { */ /* str = realloc(str, strlen(str) + commas + 1); */ /* for (size_t j = 0; j < commas; j++) { */ /* strncat(str, ",", 1); */ /* } */ /* } */ /* fputs(str, csv->csv->temp); */ /* free(str); */ /* } */ /* } */ /* else { /\* Row exceeds limit *\/ */ /* /\* Copy entire file *\/ */ /* char buf[BUFSIZ]; */ /* size_t size; */ /* while (size = fread(buf, 1, BUFSIZ, csv->csv->file)) { */ /* fwrite(buf, 1, size, csv->csv->temp); */ /* } */ /* /\* Print out commas on rows before newstr *\/ */ /* for (size_t i = csv->csv->rows; i < row; i++) { */ /* for (size_t j = 0; j < csv->csv->cols; j++) */ /* fputc(',', csv->csv->temp); */ /* fputc('\n', csv->csv->temp); */ /* } */ /* fputs(newstr, csv->csv->temp); */ /* } */ /* /\* Update csv *\/ */ /* if (_easycsv_update(csv->csv) < 0) */ /* return -1; */ /* /\* END UPDATE CSV *\/ */ /* free(rowstr); // including pch */ /* free(newstr); */ /* return 0; */ /* } */ /* int */ /* easycsv_insertcolumnvalue(easycsv *csv, */ /* const char *col, */ /* const unsigned int row, */ /* const char *val) */ /* { */ /* return easycsv_insertcolumnvaluemode(csv, col, row, val, EASYCSV_REPLACE); */ /* } */ /* int */ /* easycsv_insertcolumnvaluemode(easycsv *csv, */ /* const char *col, */ /* const unsigned int row, */ /* const char *val, */ /* const EASYCSV_VALMODE valmode) */ /* { */ /* /\* ARGS CHECK *\/ */ /* if (_easycsv_checkcsvandstring_two(csv->csv, col, val) < 0) */ /* return -1; */ /* if (row == 0) { */ /* _easycsv_printerror(csv->csv, EASYCSV_ZEROROW); */ /* return -1; */ /* } */ /* /\* END ARGS CHECK *\/ */ /* int colnum = _easycsv_getcolumn(csv->csv, col); */ /* if (colnum < 0) { */ /* _easycsv_printerror(csv->csv, EASYCSV_COLNUMFAIL); */ /* return -1; */ /* } */ /* return easycsv_insertvaluemode(csv, val, colnum, row, valmode); */ /* } */ /*** Modifications, push ***/ /* int */ /* easycsv_pushcolumn(easycsv *csv, */ /* const char *col) */ /* { */ /* /\* ARGS CHECK *\/ */ /* if (_easycsv_checkcsvandstring_one(csv->csv, col) < 0) */ /* return -1; */ /* /\* END ARGS CHECK *\/ */ /* if (csv->mode == EASYCSV_R) { */ /* _easycsv_printerror(csv->csv, EASYCSV_UNWRITABLE); */ /* return -1; */ /* } */ /* if ((csv->mode == EASYCSV_W) && (access(csv->csv->fp, F_OK) < 0)) { */ /* /\* If the file doesn't exist, just put the col */ /* in the file *\/ */ /* if (fputs(col, csv->csv->file) < 0) { */ /* _easycsv_printerror(csv->csv, EASYCSV_PUSHCOLFAIL); */ /* return -1; */ /* } */ /* return 0; */ /* } */ /* /\* Grab first row *\/ */ /* char *str = _easycsv_getrow(csv->csv, 1); */ /* char *pch = NULL; */ /* size_t i; */ /* /\* Find empty column in first row *\/ */ /* for (i = 1; i < csv->csv->cols; i++) { */ /* if (strcspn(pch, ",") == 0) */ /* break; */ /* pch = strchr(str, ','); */ /* pch++; */ /* } */ /* /\* No empty columns in first row *\/ */ /* if (i == csv->csv->cols) */ /* i++; */ /* return easycsv_insertvalue(csv, col, i, 1); */ /* /\*size_t ststr = strlen(str); */ /* size_t stcol = strlen(col); */ /* realloc(str, ststr + stcol + 2); // 1 for null and 1 for comma */ /* strncat(str + ststr, ",", 1); */ /* strncat(str + ststr + 1, col, stcol); */ /* // Put str in temp file */ /* if (fputs(str, csv->csv->temp) < 0) { */ /* _easycsv_printerror(csv->csv, EASYCSV_PUSHCOLFAIL); */ /* return -1; */ /* } */ /* free(str); */ /* // Copy every row following the first into temp */ /* for (int i = 2; i <= csv->csv->rows; i++) { */ /* char *row = _easycsv_getrow(csv, i); */ /* fputs(row, csv->csv->temp); */ /* free(row); */ /* }*\/ */ /* } */ /* int */ /* easycsv_pushcolumnvalue(easycsv *csv, */ /* const char *col, */ /* const char *val) */ /* { */ /* /\* ARGS CHECK *\/ */ /* if (_easycsv_checkcsvandstring_two(csv->csv, col, val) < 0) */ /* return -1; */ /* /\* ARGS CHECK *\/ */ /* int colnum = _easycsv_getcolumn(csv->csv, col); */ /* if (colnum < 0) { */ /* _easycsv_printerror(csv->csv, EASYCSV_COLNUMFAIL); */ /* return -1; */ /* } */ /* /\* Find a free cell under col within csv->csv->cols limits, */ /* if there is none, generate a new row *\/ */ /* unsigned int row; */ /* EASYCSV_ERRORMSG temp_error = csv->csv->error; */ /* csv->csv->error = EASYCSV_ERROROFF; */ /* for (row = 2; row <= csv->csv->cols; row++) */ /* if (easycsv_readvalue(csv, colnum, row) != NULL) */ /* break; */ /* csv->csv->error = temp_error; */ /* /\* All rows are filled, generate new row *\/ */ /* if (row > csv->csv->cols) */ /* csv->csv->rows++; */ /* /\* ROW WILL NOT BE GENERATED \\ row < csv->csv->rows *\/ */ /* return easycsv_insertvalue(csv, val, colnum, row); */ /* } */ /*** Modifications, delete ***/ /* int */ /* easycsv_deletevalue(easycsv *csv, */ /* const unsigned int col, */ /* const unsigned int row) */ /* { */ /* return easycsv_insertvalue(csv, "", col, row); */ /* } */ /* int */ /* easycsv_deletecolumnint(easycsv *csv, */ /* const unsigned int col) */ /* { */ /* /\* ARGS CHECK *\/ */ /* if (csv == NULL) { */ /* _easycsv_printerror(csv->csv, EASYCSV_NULLCSV); */ /* return -1; */ /* } */ /* if (col == 0) { */ /* _easycsv_printerror(csv->csv, EASYCSV_ZEROCOL); */ /* return -1; */ /* } */ /* if (col > csv->csv->cols) { */ /* _easycsv_printerror(csv->csv, EASYCSV_OVERMAXCOL); */ /* return -1; */ /* } */ /* /\* END ARGS CHECK *\/ */ /* for (unsigned int i = 1; i <= csv->csv->cols; i++) { */ /* if (easycsv_readvalue(csv, col, i) == NULL) */ /* break; */ /* if (easycsv_deletevalue(csv, col, i) < 0) */ /* return -1; */ /* } */ /* return 0; */ /* } */ /* int */ /* easycsv_deletecolumnstr(easycsv *csv, */ /* const char *col) */ /* { */ /* /\* ARGS CHECK *\/ */ /* if (_easycsv_checkcsvandstring_one(csv->csv, col) < 0) */ /* return -1; */ /* /\* END ARGS CHECK *\/ */ /* int colnum = _easycsv_getcolumn(csv->csv, col); */ /* if (colnum < 0) */ /* return -1; */ /* return easycsv_deletecolumnint(csv, colnum); */ /* } */ /* int */ /* easycsV_deleterowint(easycsv *csv, */ /* const unsigned int row) */ /* { */ /* return 0; */ /* } */