diff options
Diffstat (limited to 'csv-parse.c')
-rw-r--r-- | csv-parse.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/csv-parse.c b/csv-parse.c new file mode 100644 index 0000000..6feefcb --- /dev/null +++ b/csv-parse.c @@ -0,0 +1,113 @@ +#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); + } +} |