glider/utils/mxc_waveform_asm/csv.c
2024-05-14 18:32:10 -04:00

143 lines
2.9 KiB
C

#include <stdlib.h>
#include <string.h>
void free_csv_line( char **parsed ) {
char **ptr;
for ( ptr = parsed; *ptr; ptr++ ) {
free( *ptr );
}
free( parsed );
}
static int count_fields( const char *line ) {
const char *ptr;
int cnt, fQuote;
for ( cnt = 1, fQuote = 0, ptr = line; *ptr; ptr++ ) {
if ( fQuote ) {
if ( *ptr == '\"' ) {
if ( ptr[1] == '\"' ) {
ptr++;
continue;
}
fQuote = 0;
}
continue;
}
switch( *ptr ) {
case '\"':
fQuote = 1;
continue;
case ',':
cnt++;
continue;
default:
continue;
}
}
if ( fQuote ) {
return -1;
}
return cnt;
}
/*
* Given a string containing no linebreaks, or containing line breaks
* which are escaped by "double quotes", extract a NULL-terminated
* array of strings, one for every cell in the row.
*/
char **parse_csv( const char *line ) {
char **buf, **bptr, *tmp, *tptr;
const char *ptr;
int fieldcnt, fQuote, fEnd;
fieldcnt = count_fields( line );
if ( fieldcnt == -1 ) {
return NULL;
}
buf = malloc( sizeof(char*) * (fieldcnt+1) );
if ( !buf ) {
return NULL;
}
tmp = malloc( strlen(line) + 1 );
if ( !tmp ) {
free( buf );
return NULL;
}
bptr = buf;
for ( ptr = line, fQuote = 0, *tmp = '\0', tptr = tmp, fEnd = 0; ; ptr++ ) {
if ( fQuote ) {
if ( !*ptr ) {
break;
}
if ( *ptr == '\"' ) {
if ( ptr[1] == '\"' ) {
*tptr++ = '\"';
ptr++;
continue;
}
fQuote = 0;
}
else {
*tptr++ = *ptr;
}
continue;
}
switch( *ptr ) {
case '\"':
fQuote = 1;
continue;
case '\0':
fEnd = 1;
case ',':
*tptr = '\0';
*bptr = strdup( tmp );
if ( !*bptr ) {
for ( bptr--; bptr >= buf; bptr-- ) {
free( *bptr );
}
free( buf );
free( tmp );
return NULL;
}
bptr++;
tptr = tmp;
if ( fEnd ) {
break;
} else {
continue;
}
default:
*tptr++ = *ptr;
continue;
}
if ( fEnd ) {
break;
}
}
*bptr = NULL;
free( tmp );
return buf;
}