#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "csv.h"
enum { NOMEM = -2 };
typedef struct csv_field {
int csv_num;
char *line;
char *sline;
int maxline;
char **field;
int maxfield;
int nfield;
char *fieldsep;
} CsvFld;
static CsvFld* pcsvfld = NULL;
static int ncsvfld = 0;
static CsvNum unicsvnum = 0;
CsvFld* pcf_elem(CsvNum cn)
{
int i;
if (cn < 0) return NULL;
for (i = 0; i < ncsvfld; i++) {
if (pcsvfld[i].csv_num == cn) break;
}
if (i >= ncsvfld) return NULL;
return &(pcsvfld[i]);
}
static int reset(CsvNum cn)
{
CsvFld* p;
if((p=pcf_elem(cn)) == NULL) return -1;
free(p->line);
free(p->sline);
free(p->field);
free(p->fieldsep);
p->line = NULL;
p->sline = NULL;
p->field = NULL;
p->maxline = p->maxfield = p->nfield = 0;
return 0;
}
void init(CsvNum cn)
{
int i;
if (cn < 0) return;
for (i = 0; i < ncsvfld; i++) {
if (pcsvfld[i].csv_num == cn) break;
}
if (i >= ncsvfld) i = ncsvfld-1;
printf("elements:%d address:%p\n", ncsvfld, &pcsvfld[i]);
pcsvfld[i].csv_num = cn;
pcsvfld[i].line = NULL;
pcsvfld[i].sline = NULL;
pcsvfld[i].maxline = 0;
pcsvfld[i].field = NULL;
pcsvfld[i].maxfield = 0;
pcsvfld[i].nfield = 0;
pcsvfld[i].fieldsep = NULL;
}
CsvNum csvnew(char* fldsp)
{
CsvFld* newpcf;
if (pcsvfld == NULL || ncsvfld == 0) {
newpcf = (CsvFld*) malloc(sizeof(CsvFld));
if (newpcf == NULL) return NOMEM;
ncsvfld++;
}
else {
newpcf = (CsvFld*) realloc(pcsvfld, sizeof(CsvFld) * ++ncsvfld);
if (newpcf == NULL) return NOMEM;
}
pcsvfld = newpcf;
unicsvnum++;
init(unicsvnum);
pcsvfld[ncsvfld-1].fieldsep = (char*) malloc(strlen(fldsp)+1);
if (pcsvfld[ncsvfld-1].fieldsep == NULL) return NOMEM;
memmove(pcsvfld[ncsvfld-1].fieldsep, fldsp, strlen(fldsp)+1);
return unicsvnum;
}
int csvfree(CsvNum cn)
{
int i;
CsvFld* newpcf;
for (i = 0; i < ncsvfld; i++) {
if (pcsvfld[i].csv_num == cn) break;
}
if (i >= ncsvfld) return -1;
reset(cn);
memmove(pcsvfld+i, pcsvfld+i+1, (sizeof(CsvFld)*(ncsvfld-i-1)));
newpcf = (CsvFld*)realloc(pcsvfld, sizeof(CsvFld) * --ncsvfld);
if (newpcf == NULL) return NOMEM;
pcsvfld = newpcf;
return 0;
}
static char *advquoted(CsvNum cn, char *p)
{
int i, j, elm;
for (i = j = 0; p[j] != '\0'; i++, j++) {
if (p[j] == '"' && p[++j] != '"') {
int k = strcspn(p+j, pcf_elem(cn)->fieldsep);
memmove(p+i, p+j, k);
i += k;
j += k;
break;
}
p[i] = p[j];
}
p[i] = '\0';
return p + j;
}
int isfldsep(CsvNum cn, char c)
{
char *p;
p = pcf_elem(cn)->fieldsep;
do {
if (*(p++) == c) return 1;
} while (*p);
return 0;
}
static int split(CsvNum cn)
{
char *p, **newf;
char *sepp;
int sepc;
CsvFld* pcf;
if ((pcf=pcf_elem(cn)) == NULL) return -1;
pcf->nfield = 0;
if (pcf->line[0] == '\0')
return 0;
strcpy(pcf->sline, pcf->line);
p = pcf->sline;
do {
if (pcf->nfield >= pcf->maxfield) {
pcf->maxfield *= 2;
newf = (char **) realloc(pcf->field, pcf->maxfield * sizeof(pcf->field[0]));
if (newf == NULL)
return NOMEM;
pcf->field = newf;
}
if (*p == '"')
sepp = advquoted(cn, ++p);
else
sepp = p + strcspn(p, pcf->fieldsep);
sepc = sepp[0];
sepp[0] = '\0';
pcf->field[(pcf->nfield)++] = p;
p = sepp + 1;
} while (isfldsep(cn, sepc));
return pcf->nfield;
}
static int endofline(FILE *fin, int c)
{
int eol;
eol = (c=='\r' || c=='\n');
if (c == '\r') {
c = getc(fin);
if (c != '\n' && c != EOF)
ungetc(c, fin);
}
return eol;
}
char *csvgetline(FILE *fin, CsvNum cn)
{
int i, c;
char *newl, *news;
CsvFld* pcf;
if ((pcf=pcf_elem(cn)) == NULL) return NULL;
if (pcf->line == NULL) {
pcf->maxline = pcf->maxfield = 1;
pcf->line = (char *) malloc(pcf->maxline);
pcf->sline = (char *) malloc(pcf->maxline);
pcf->field = (char **) malloc(pcf->maxfield*sizeof(pcf->field[0]));
if (pcf->line == NULL || pcf->sline == NULL || pcf->field == NULL) {
reset(cn);
return NULL;
}
}
for (i=0; (c=getc(fin))!=EOF && !endofline(fin, c); i++) {
if (i >= pcf->maxline-1) {
pcf->maxline *= 2;
newl = (char *) realloc(pcf->line, pcf->maxline);
news = (char *) realloc(pcf->sline, pcf->maxline);
if (newl == NULL || news == NULL) {
reset(cn);
return NULL;
}
pcf->line = newl;
pcf->sline = news;
}
pcf->line[i] = c;
}
pcf->line[i] = '\0';
if (split(cn) == NOMEM) {
reset(cn);
return NULL;
}
return (c == EOF && i == 0) ? NULL : pcf->line;
}
char *csvfield(CsvNum cn, int n)
{
CsvFld* p;
if ((p=pcf_elem(cn)) == NULL) return NULL;
if (n < 0 || n >= p->nfield)
return NULL;
return p->field[n];
}
int csvnfield(CsvNum cn)
{
CsvFld* p;
if ((p=pcf_elem(cn)) == NULL) return -1;
return p->nfield;
}
#include <stdio.h>
#include "csv.h"
int main(void)
{
int i, j;
char *line;
CsvNum cn;
for (j = 0; j < 3; j++) {
cn = csvnew(",");
printf("独自csvフィールド取得値%d\n",cn);
while ((line = csvgetline(stdin, cn)) != NULL) {
printf("line = '%s'\n", line);
for (i = 0; i < csvnfield(cn); i++)
printf("field[%d] = '%s'\n", i , csvfield(cn, i));
}
if(csvfree(cn)==-1) printf("error\n");
}
return 0;
}
typedef int CsvNum;
extern char *csvgetline(FILE *F, CsvNum cn);
extern char *csvfield(CsvNum cn, int n);
extern int csvnfield(CsvNum cn);
extern CsvNum csvnew(char* fieldsep);
extern int csvfree(CsvNum cn);