#include "csv-parse.h" token *tokens = 0; token *last_tok = 0; line *lines = 0; line *last_line = 0; inline int iseol(char c) { return (c == '\n' || c == '\0'); } token *make_token(char *value) { token *new_tok = malloc(sizeof(token)); (last_tok) ? (last_tok->next = new_tok) : (tokens = new_tok); new_tok->value = value; new_tok->next = NULL; last_tok = new_tok; return new_tok; } line *get_line(char *str) { token *t = NULL; int skip = 0; /* Blank column count. */ int isblank = 0; /* Used to check if this line is blank. */ int i = 0; while (!iseol(str[i])) { char *value = NULL; switch (str[i]) { case '\"': for (++str; str[i] != '\"' && !iseol(str[i]); i++); break; default : for ( ; str[i] != ',' && !iseol(str[i]); i++); break; } /* Is there anything in this column? */ if (i) { /* Copy the column contents, and null terminate it. */ value = malloc(i+1); memcpy(value, str, i); value[i] = '\0'; /* Create the new column. */ t = make_token(value); t->skip = skip; skip = 0; t = t->next; } else { value = NULL; skip += (t == NULL); } str += i+1; /* Shift the start of the line to the start of the next column. */ i = 0; } isblank = (tokens == NULL && last_tok == NULL); /* Is this line blank? */ if (!isblank) { line *l = malloc(sizeof(line)); /* If there was a previous line, set the next line to the new line. * Otherwise, set the starting line to the new line. */ (last_line) ? (last_line->next = l) : (lines = l); /* Save the starting, and ending columns for this line. */ l->tok = tokens; l->last_tok = last_tok; tokens = NULL; last_tok = NULL; l->next = NULL; last_line = l; return l; } else { return NULL; } } void parse_csv(FILE *fp) { char buf[0x1000]; int blank_lines = 0; line *l; while (fgets(buf, sizeof(buf), fp) != NULL && !feof(fp)) { l = get_line(buf); blank_lines += (l == NULL); if (l != NULL) { l->skip = blank_lines; blank_lines = 0; } } } void free_tokens(token *t, token *lt, int row) { token *tok; int i = 0; int skip = 0; while (t != NULL) { tok = t; free(tok->value); t = t->next; i++; free(tok); } } void free_lines() { line *l = lines; line *ln; int i = 0; while (l != NULL) { free_tokens(l->tok, l->last_tok, i); i++; ln = l; l = l->next; free(ln); } }