Implement csv_save().

This commit is contained in:
@@@No user configured@@@ 2016-05-16 13:49:58 +02:00
parent 2808591bf6
commit e7c1b7d973

View file

@ -17,13 +17,16 @@
typedef struct { typedef struct {
char delim; char * delim;
unsigned int rows; unsigned int rows;
unsigned int cols; unsigned int cols;
char ** table; char ** table;
} CSV; } CSV;
/* trim whitespaces from left & right of a string */
/**
* Utility function to trim whitespaces from left & right of a string
*/
int trim(char ** str) { int trim(char ** str) {
int trimmed; int trimmed;
int n; int n;
@ -49,20 +52,40 @@ int trim(char ** str) {
return trimmed; return trimmed;
} }
CSV * csv_create() {
/**
* De-allocate csv structure
*/
int csv_destroy(CSV * csv) {
if (csv == NULL) { return 0; }
if (csv->table != NULL) { free(csv->table); }
if (csv->delim != NULL) { free(csv->delim); }
free(csv);
return 0;
}
/**
* Allocate memory for a CSV structure
*/
CSV * csv_create(unsigned int cols, unsigned int rows) {
CSV * csv; CSV * csv;
csv = malloc(sizeof(CSV)); csv = malloc(sizeof(CSV));
csv->rows = 0; csv->rows = rows;
csv->cols = 0; csv->cols = cols;
csv->table = NULL; csv->delim = strdup(",");
csv->table = malloc(sizeof(char *) * cols * rows);
if (csv->table == NULL) { goto error; }
memset(csv->table, 0, sizeof(char *) * cols * rows);
return csv; return csv;
}
int csv_destroy(CSV * csv) { error:
free(csv); csv_destroy(csv);
return 0; return NULL;
} }
@ -70,7 +93,9 @@ int csv_destroy(CSV * csv) {
* Get value in CSV table at COL, ROW * Get value in CSV table at COL, ROW
*/ */
char * csv_get(CSV * csv, unsigned int col, unsigned int row) { char * csv_get(CSV * csv, unsigned int col, unsigned int row) {
return NULL; unsigned int idx;
idx = col + (row * csv->cols);
return csv->table[idx];
} }
@ -78,9 +103,32 @@ char * csv_get(CSV * csv, unsigned int col, unsigned int row) {
* Set value in CSV table at COL, ROW * Set value in CSV table at COL, ROW
*/ */
int csv_set(CSV * csv, unsigned int col, unsigned int row, char * value) { int csv_set(CSV * csv, unsigned int col, unsigned int row, char * value) {
unsigned int idx;
idx = col + (row * csv->cols);
csv->table[idx] = value;
return 0; return 0;
} }
void csv_display(CSV * csv) {
int row, col;
char * content;
if ((csv->rows == 0) || (csv->cols==0)) {
printf("[Empty table]\n");
return ;
}
printf("\n[Table cols=%d rows=%d]\n", csv->cols, csv->rows);
for (row=0; row<csv->rows; row++) {
printf("[|");
for (col=0; col<csv->cols; col++) {
content = csv_get(csv, col, row);
printf("%s\t|", content);
}
printf("]\n");
}
printf("\n");
}
/* Resize CSV table /* Resize CSV table
* - grow columns: on each row, add missing columns cells * - grow columns: on each row, add missing columns cells
* - grow rows: add now rows, with all columns count * - grow rows: add now rows, with all columns count
@ -97,14 +145,12 @@ int csv_resize(CSV * old_csv, unsigned int new_cols, unsigned int new_rows) {
bool in_old, in_new; bool in_old, in_new;
/* Build a new (fake) csv */ /* Build a new (fake) csv */
new_csv = csv_create(); new_csv = csv_create(new_cols, new_rows);
if (new_csv == NULL) { goto error; }
new_csv->rows = new_rows; new_csv->rows = new_rows;
new_csv->cols = new_cols; new_csv->cols = new_cols;
new_csv->table = malloc(sizeof(char *) * new_cols * new_rows);
memset(new_csv->table, 0, sizeof(char *) * new_cols * new_rows);
if (new_csv->table == NULL) { goto error; }
max_cols = (new_cols > old_csv->cols)? new_cols : old_csv->cols; max_cols = (new_cols > old_csv->cols)? new_cols : old_csv->cols;
max_rows = (new_rows > old_csv->rows)? new_rows : old_csv->rows; max_rows = (new_rows > old_csv->rows)? new_rows : old_csv->rows;
@ -122,10 +168,7 @@ int csv_resize(CSV * old_csv, unsigned int new_cols, unsigned int new_rows) {
/* destroy data */ /* destroy data */
content = csv_get(old_csv, cur_col, cur_row); content = csv_get(old_csv, cur_col, cur_row);
free(content); free(content);
} else { } else { /* skip */ }
/* skip */
/* csv_set(new_csv, cur_col, cur_row, NULL); */
}
} }
} }
/* on rows */ /* on rows */
@ -133,6 +176,9 @@ int csv_resize(CSV * old_csv, unsigned int new_cols, unsigned int new_rows) {
old_csv->rows = new_rows; old_csv->rows = new_rows;
old_csv->cols = new_cols; old_csv->cols = new_cols;
old_csv->table = new_csv->table; old_csv->table = new_csv->table;
new_csv->table = NULL;
csv_destroy(new_csv);
return 0; return 0;
error: error:
@ -151,34 +197,52 @@ int csv_open(CSV * csv, char * filename) {
fp = fopen(filename, "r"); fp = fopen(filename, "r");
if (fp == NULL) { exit(EXIT_FAILURE); } if (fp == NULL) { goto error; }
m_rows = 0; m_rows = 0;
m_cols = 0; m_cols = 0;
while(fgets(line, sizeof(line), fp) != NULL) { while(fgets(line, sizeof(line), fp) != NULL) {
/* printf("Got line: %s", line); */
m_rows += 1; m_rows += 1;
cols = 0; cols = 0;
lineptr = line; lineptr = line;
while ((token = strtok(lineptr, ",")) != NULL) { while ((token = strtok(lineptr, csv->delim)) != NULL) {
lineptr = NULL; lineptr = NULL;
trim(&token); trim(&token);
printf("%s\t|", token);
cols += 1; cols += 1;
if (cols > m_cols) { m_cols = cols; } if (cols > m_cols) { m_cols = cols; }
csv_resize(csv, m_cols, m_rows); csv_resize(csv, m_cols, m_rows);
csv_set(csv, cols-1, m_rows-1, strdup(token));
} }
printf("\n");
} }
fclose(fp); fclose(fp);
csv->delim = '\t';
csv->rows = m_rows; csv->rows = m_rows;
csv->cols = m_cols; csv->cols = m_cols;
return 0; return 0;
error:
fclose(fp);
printf("Unable to open %s for reading.", filename);
return -1;
} }
int csv_save(CSV * csv, char * filename) { int csv_save(CSV * csv, char * filename) {
FILE * fp;
int row, col;
char * content;
fp = fopen(filename, "w");
for (row=0; row<csv->rows; row++) {
for (col=0; col<csv->cols; col++) {
content = csv_get(csv, col, row);
fprintf(fp, "%s%s", content,
((col == csv->cols-1) ? "" : csv->delim) );
}
fprintf(fp, "\n");
}
fclose(fp);
return 0; return 0;
} }
@ -187,17 +251,18 @@ int main(int argc, char ** argv) {
printf("%s\n%s\n\n",TITLE, URL); printf("%s\n%s\n\n",TITLE, URL);
csv = csv_create(0, 0);
csv = csv_create();
csv_open(csv, "fixtures/csv-data-manipulation.csv"); csv_open(csv, "fixtures/csv-data-manipulation.csv");
csv_display(csv);
csv_set(csv, 0, 0, "Column0"); csv_set(csv, 0, 0, "Column0");
csv_set(csv, 1, 1, "100"); csv_set(csv, 1, 1, "100");
csv_set(csv, 2, 2, "200"); csv_set(csv, 2, 2, "200");
csv_set(csv, 3, 3, "300"); csv_set(csv, 3, 3, "300");
csv_set(csv, 4, 4, "400"); csv_set(csv, 4, 4, "400");
csv_display(csv);
csv_save(csv, "fixtures/csv-data-manupulation.out.csv"); csv_save(csv, "tmp/csv-data-manupulation.out.csv");
csv_destroy(csv); csv_destroy(csv);
return 0; return 0;