[q-lang-cvs] q-csv README,1.6,1.7 csv.c,1.3,1.4 csv.q,1.4,1.5
Brought to you by:
agraef
From: RER <ed...@us...> - 2008-01-13 17:27:22
|
Update of /cvsroot/q-lang/q-csv In directory sc8-pr-cvs16.sourceforge.net:/tmp/cvs-serv31912 Modified Files: README csv.c csv.q Log Message: updated README, read samples, write samples, csv.c, and csv.q Index: README =================================================================== RCS file: /cvsroot/q-lang/q-csv/README,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** README 10 Jan 2008 23:41:21 -0000 1.6 --- README 13 Jan 2008 17:27:14 -0000 1.7 *************** *** 28,34 **** - freadcsv_data converts non-quoted numeric fields to integer or double values ! automatically. fwritecsv_data writes integer or double values to non-quoted fields. The ! handling of quoted or non-quoted fields is handled automatically. - freadcsv_string and fwritecsv_string read all fields as strings --- 28,37 ---- - freadcsv_data converts non-quoted numeric fields to integer or double values ! automatically. Invalidly formated CSV strings force the invocation of a ! 'csv_error MSG' rule. fwritecsv_data writes integer or double values to non-quoted fields. The ! handling of quoted or non-quoted fields is automatic. Fields with types ! other than floats, integers, or strings force the invocation of a ! 'csv_error MSG' rule. - freadcsv_string and fwritecsv_string read all fields as strings *************** *** 36,51 **** fwritecsv_string writes all values as quoted fields. ! The primary interface functions freadcsv and fwritecsv are defined to be ! equivalent to the _data variants by default. If necessary, you can change this ! by adding appropriate definitions to your program, i.e.: ! ! freadcsv = freadcsv_string; ! fwritecsv = fwritecsv_string; The routines described above read/write one record at a time. Additional ! functions (freadfilecsv and fwritefilecsv, again with corresponding _data and ! _string variants) are provided to convert between entire CSV files and lists ! of tuples. Note that these require that the entire data fits into RAM and will ! thus be inefficient for huge datasets. NOTES --- 39,51 ---- fwritecsv_string writes all values as quoted fields. ! The primary interface function fread_csvstr reads a string from a file ! with embedded end of lines. It does not check for a valid record. The two ! other primary interface functions, csvstr_to_tuple and tuple_to_csvstr ! convert CSV formated strings to tuples and vice versa. The routines described above read/write one record at a time. Additional ! functions (freadfilecsv_data and fwritefilecsv_data) are provided to convert ! between entire CSV files and lists of tuples. Note that these require that ! the entire data fits into RAM and will thus be inefficient for huge datasets. NOTES *************** *** 54,57 **** --- 54,60 ---- 4180 rules. + - The write functions fail when field types other than strings, integers, or + floats are given. + - MS Excel files should be read using _string variants as Excel does not quote values such as 0004. These types of values will be converted to integers and *************** *** 61,67 **** TO DO - - String to Tuple and Tuple to String versions corresponding to the reading - and writing operations will be provided. - - Operations for fixed length record reading and writing will be provided. --- 64,67 ---- Index: csv.c =================================================================== RCS file: /cvsroot/q-lang/q-csv/csv.c,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** csv.c 12 Jan 2008 13:37:49 -0000 1.3 --- csv.c 13 Jan 2008 17:27:14 -0000 1.4 *************** *** 1,3 **** ! /* CSV according to RFC 4180 (http://www.ietf.org/rfc/rfc4180.txt) This is free software; you can redistribute it and/or --- 1,3 ---- ! /* CSV according to RFC 4180 (http://tools.ietf.rg/html/rfc4180) This is free software; you can redistribute it and/or *************** *** 16,22 **** ! Written by Eddie Rucker 3-12 Jan, 2008 */ ! ! /* Test to see if cvs is working */ #include <stdio.h> --- 16,20 ---- ! Written by Eddie Rucker 3-13 Jan, 2008 */ #include <stdio.h> *************** *** 24,33 **** #include <libq.h> #define FORCEQUOTE 0 ! #define AUTOQUOTE 1 - MODULE(csv); /* convience function to convert numbers */ expr *convert(char *s, int cvt_flag) { long i; --- 22,75 ---- #include <libq.h> + MODULE(csv); + + #define BSIZE 512 #define FORCEQUOTE 0 ! #define AUTOQUOTE 1 ! ! /* fread_block reads embbeded '\n's ! Does not account for badly formatted records */ ! ! FUNCTION (csv, fread_csvstr, argc, argv) ! { ! FILE *fp; ! char *buff, *bp, *tp, *strdl; ! int len = 0, q_cnt = 0, size = BSIZE; ! register int c; ! ! if (argc != 2 ! || !isfile(argv[0], &fp) ! || !isstr(argv[1], &strdl)) ! return __FAIL; ! ! if (!(buff = (char *)malloc(size))) ! return NULL; ! ! bp = buff; ! while ((c = fgetc(fp)) != EOF) { ! if (len > size) { ! if (!(tp = (char *)realloc(buff, size <<= 1))) { ! free(buff); ! return __ERROR; ! } ! buff = tp; ! bp = buff + len; ! } ! if (c == '\n' && !(q_cnt % 2)) ! break; ! if (c == *strdl) ! ++q_cnt; ! ++len; ! *bp++ = c; ! } ! buff = (char *)realloc(buff, len+2); ! *bp++ = c; ! *bp = 0; ! return mkstr(buff); ! } /* convience function to convert numbers */ + expr *convert(char *s, int cvt_flag) { long i; *************** *** 48,118 **** } ! #define putfld \ ! if (fld_len >= fld_size - 1) { \ ! if (!(tfield = realloc(field, fld_size <<= 1))) \ ! goto st30; \ ! field = tfield; \ ! } \ ! sp = field + fld_len++; \ ! *sp++ = c /* force == 0 forces the field to be quoted */ #define putrec(force) \ ! *sp = 0; \ if (rec_len >= rec_size - 1) { \ ! if (!(trec = realloc(rec, (rec_size += 16)*sizeof(expr)))) \ goto st30; \ rec = trec; \ } \ ! if ((rec[rec_len++] = convert(field, cvt_flag&force)) == NULL) \ goto st30 ! /* freadcsv_ ! input: (Conversion flag, File, field delimeter char, string delimeter char) ! output: tuple of fields. Notes: ! \r char is treated as white space except inside "" ! */ ! FUNCTION(csv, freadcsv_, argc, argv) ! { ! FILE *fp; ! char *field, *tfield, *sp, *fld_dlm, *str_dlm; ! int n, fld_size = 128, fld_len, rec_size = 128, ws_cnt = 0, rec_len = 0, ! cvt_flag, exit_type = 0; ! register int c; ! expr *rec, *trec, *xs; ! if (argc != 1 || !istuple(argv[0], &n, &xs) ! || n != 4 ! || !isbool(xs[0], &cvt_flag) ! || !isfile(xs[1], &fp) ! || !isstr(xs[2], &fld_dlm) ! || !isstr(xs[3], &str_dlm)) return __FAIL; ! ! if (!(field = malloc(fld_size))) return __ERROR; ! ! if (!(rec = malloc(rec_size*sizeof(expr)))) { free(field); return __ERROR; } ! ! st0: c = fgetc(fp); ! sp = field; fld_len = 0; ! if (c == *fld_dlm) { putrec(FORCEQUOTE); goto st0; ! } else if (c == *str_dlm) { goto st1; ! } else if (c == '\n' || c == EOF) { putrec(FORCEQUOTE); goto st10; ! } else if (c == ' ' || c == '\t' || c == '\r') { /* fld_dlm might be ws make sure it is after (c == *fld_dlm) */ goto st0; --- 90,169 ---- } ! ! #define putfld \ ! if (fld_len >= fld_size - 1) { \ ! if (!(tfield = (char *)realloc(field, fld_size <<= 1))) \ ! goto st30; \ ! field = tfield; \ ! } \ ! fieldp = field + fld_len++; \ ! *fieldp++ = *sp ! /* force == 0 forces the field to be quoted */ + #define putrec(force) \ ! *fieldp = 0; \ if (rec_len >= rec_size - 1) { \ ! if (!(trec = (expr *)realloc(rec, (rec_size += 16)*sizeof(expr)))) \ goto st30; \ rec = trec; \ } \ ! if ((rec[rec_len++] = convert(field, cvt_f&force)) == NULL) \ goto st30 ! /* convert a CSV string to a tuple of fields ! input: ! arg[0]: (Conversion flag, field delimeter char, string delimeter char) ! arg[1]: CSV formated string ! ! output: tuple of fields ! exceptions: ! Returns __ERROR if no more memory is available. ! Invokes 'csv_error MSG' if the string is badly formated Notes: ! \r char is treated as white space except inside "" */ ! FUNCTION(csv, csvstr_to_tuple, argc, argv) ! { ! int n, cvt_f, fld_size = 256, fld_len, rec_size = 64, ws_cnt = 0, ! rec_len = 0, exit_type = 0; ! char *field, *tfield, *fieldp, *s, *flddl, *strdl, errmsg[80]; ! expr *xs, *rec, *trec; ! register char *sp; ! ! if (argc != 2 || !istuple(argv[0], &n, &xs) ! || n != 3 ! || !isbool(xs[0], &cvt_f) ! || !isstr(xs[1], &flddl) ! || !isstr(xs[2], &strdl) ! || !isstr(argv[1], &s)) return __FAIL; ! ! if (!(field = (char *)malloc(fld_size))) return __ERROR; ! ! if (!(rec = (expr *)malloc(rec_size*sizeof(expr)))) { free(field); return __ERROR; } ! ! sp = s - 1; ! st0: ++sp; ! fieldp = field; fld_len = 0; ! if (!strncmp(sp, flddl, 1)) { putrec(FORCEQUOTE); goto st0; ! } else if (!strncmp(sp, strdl, 1)) { goto st1; ! } else if (*sp == '\n' || *sp == EOF) { putrec(FORCEQUOTE); goto st10; ! } else if (isspace(*sp)) { /* fld_dlm might be ws make sure it is after (c == *fld_dlm) */ goto st0; *************** *** 121,129 **** goto st4; } ! st1: c = fgetc(fp); ! if (c == *str_dlm) { goto st2; ! } ! else if (c == EOF) { goto st20; } else { --- 172,179 ---- goto st4; } ! st1: ++sp; ! if (!strncmp(sp, strdl, 1)) { goto st2; ! } else if (*sp == EOF) { goto st20; } else { *************** *** 131,145 **** goto st1; } ! st2: c = fgetc(fp); ! if (c == *str_dlm) { putfld; goto st1; ! } else if (c == *fld_dlm) { putrec(FORCEQUOTE); goto st0; ! } else if (c == '\n' || c == EOF) { putrec(FORCEQUOTE); goto st10; ! } else if (c == ' ' || c == '\t' || c == '\r') { /* fld_dlm might be ws make sure it is after (c == *fld_dlm) */ goto st3; --- 181,195 ---- goto st1; } ! st2: ++sp; ! if (!strncmp(sp, strdl, 1)) { putfld; goto st1; ! } else if (!strncmp(sp, flddl, 1)) { putrec(FORCEQUOTE); goto st0; ! } else if (*sp == '\n' || *sp == EOF) { putrec(FORCEQUOTE); goto st10; ! } else if (isspace(*sp)) { /* fld_dlm might be ws make sure it is after (c == *fld_dlm) */ goto st3; *************** *** 147,171 **** goto st20; } ! st3: c = fgetc(fp); ! if (c == *fld_dlm) { putrec(FORCEQUOTE); goto st0; ! } else if (c == '\n' || c == EOF) { putrec(FORCEQUOTE); goto st10; ! } else if (c == ' ' || c == '\t' || c == '\r') { /* fld_dlm might be ws make sure it is after (c == *fld_dlm) */ goto st3; } ! st4: c = fgetc(fp); ! if (c == *fld_dlm) { putrec(AUTOQUOTE); goto st0; ! } else if (c == '\n' || c == EOF) { putrec(AUTOQUOTE); goto st10; ! } else if (c == *str_dlm) { goto st20; ! } else if (c == ' ' || c == '\t' || c == '\r') { /* fld_dlm might be ws make sure it is after (c == *fld_dlm) */ ws_cnt = 1; --- 197,223 ---- goto st20; } ! st3: ++sp; ! if (!strncmp(sp, flddl, 1)) { putrec(FORCEQUOTE); goto st0; ! } else if (*sp == '\n' || *sp == EOF) { putrec(FORCEQUOTE); goto st10; ! } else if (isspace(*sp)) { /* fld_dlm might be ws make sure it is after (c == *fld_dlm) */ goto st3; + } else { + goto st20; } ! st4: ++sp; ! if (!strncmp(sp, flddl, 1)) { putrec(AUTOQUOTE); goto st0; ! } else if (*sp == '\n' || *sp == EOF) { putrec(AUTOQUOTE); goto st10; ! } else if (!strncmp(sp, strdl, 1)) { goto st20; ! } else if (isspace(*sp)) { /* fld_dlm might be ws make sure it is after (c == *fld_dlm) */ ws_cnt = 1; *************** *** 176,189 **** goto st4; } ! st5: c = fgetc(fp); ! if (c == *fld_dlm) { ! sp -= ws_cnt; /* get rid of ws at the end of the field */ putrec(AUTOQUOTE); goto st0; ! } else if (c == '\n' || c == EOF) { ! sp -= ws_cnt; /* get rid of ws at the end of the field */ putrec(AUTOQUOTE); goto st10; ! } else if (c == ' ' || c == '\t' || c == '\r') { /* fld_dlm might be ws make sure it is after (c == *fld_dlm) */ ++ws_cnt; --- 228,241 ---- goto st4; } ! st5: ++sp; ! if (!strncmp(sp, flddl, 1)) { ! fieldp -= ws_cnt; /* get rid of ws at the end of the field */ putrec(AUTOQUOTE); goto st0; ! } else if (*sp == '\n' || *sp == EOF) { ! fieldp -= ws_cnt; /* get rid of ws at the end of the field */ putrec(AUTOQUOTE); goto st10; ! } else if (isspace(*sp)) { /* fld_dlm might be ws make sure it is after (c == *fld_dlm) */ ++ws_cnt; *************** *** 205,298 **** dispose(rec[n]); free(rec); ! if (exit_type == 1) ! return __FAIL; return __ERROR; } ! /* fwritecsv_ - input: (Conversion Flag, File, field delimeter char, string delimeter char) - Tuple - output: File. ! returns: ! __FAIL if arguments are not valid. ! __ERROR is out of memory ! */ ! FUNCTION (csv, fwritecsv_, argc, argv) { ! FILE *fp; ! int i, n, dqflag, qcnt = 0, cvt_flag; long ival; double dval; - char *fld_del, *str_del, *sval, *prt, *rt; - register char *t; expr *xs, *ys; if (argc != 2 || !istuple(argv[0], &i, &ys) ! || i != 4 ! || !isbool(ys[0], &cvt_flag) ! || !isfile(ys[1], &fp) ! || !isstr(ys[2], &fld_del) ! || !isstr(ys[3], &str_del) || !istuple(argv[1], &n, &xs)) return __FAIL; ! for (i = 0; i < n; ++i) { ! if (isint(xs[i], &ival)) ! if (cvt_flag) ! fprintf(fp, "%d", ival); else ! fprintf(fp, "%s%d%s", str_del, ival, str_del); ! else if (isfloat(xs[i], &dval)) ! if (cvt_flag) ! fprintf(fp, "%g", dval); else ! fprintf(fp, "%s%g%s", str_del, dval, str_del); ! else if (isstr(xs[i], &sval)) { /* strings are always dquoted */ ! /* count dquotes for escape quotes */ ! for (t = sval; *t; ++t) ! if (*t == *str_del) ++qcnt; ! ! if (!(prt = malloc(strlen(sval) + qcnt + 2))) ! return __ERROR; ! ! rt = prt; ! t = sval; ! while (*t) { ! if (*t == *str_del) ! *rt++ = *t; ! *rt++ = *t++; } ! *rt = 0; ! fprintf(fp, "%s%s%s", str_del, prt, str_del); ! free(prt); ! } else ! return __FAIL; ! if (i != n - 1) ! fprintf(fp, "%s", fld_del); } ! #if defined (_WIN32) ! fprintf(fp, "\r\n"); #else ! fprintf(fp, "\n"); #endif ! ! return mkvoid; } - - /* swritecsv - - input: (field delimeter char, string delimeter char) Tuple - output: CSV formatted String - - returns: - __FAIL if arguments are not valid. - __ERROR is out of memory - */ - --- 257,370 ---- dispose(rec[n]); free(rec); ! if (exit_type == 1) { ! sprintf(errmsg, "Column %d: Unexpected end of file.", (fld_len+1)); ! return mkapp(mksym(sym(csv_error)), mkstr(strdup(errmsg))); ! } return __ERROR; } ! #define resize_str \ ! if (len > size) { \ ! if (!(tstr = realloc(str, sizeof(char)*(size <<= 1)))) { \ ! free(str); \ ! return __ERROR; \ ! } \ ! str = tstr; \ ! } \ ! t = str + mark ! #define insert_num \ ! mark = len; \ ! len += strlen(tbuff); \ ! resize_str; \ ! strncpy(t, tbuff, len - mark) ! ! /* convert tuple to csv string ! input: ! arg[0]: (Conversion flag, field delimeter char, string delimeter char) ! arg[1]: tuple to be converted ! ! output: CSV formated string ! ! exceptions: ! Returns __ERROR if no more memory is available. ! Invokes 'csv_error MSG' if a field cannot be converted. ! ! Notes: ! \r char is treated as white space except inside "" */ ! ! FUNCTION (csv, tuple_to_csvstr, argc, argv) { ! int i, n, size = 256, mark, qcnt, len = 0, cvt_f; ! char *str, *tstr, *sval, *strdl, *flddl, *p, tbuff[48], errmsg[80]; long ival; double dval; expr *xs, *ys; + register char *t; if (argc != 2 || !istuple(argv[0], &i, &ys) ! || i != 3 ! || !isbool(ys[0], &cvt_f) /* unquote flag */ ! || !isstr(ys[1], &flddl) ! || !isstr(ys[2], &strdl) || !istuple(argv[1], &n, &xs)) return __FAIL; ! ! if (!(str = (char *)malloc(size))) ! return __ERROR; ! for (i = 0; i < n; ++i) { ! if (isint(xs[i], &ival)) { ! if (cvt_f) ! sprintf(tbuff, "%d%s", ival, flddl); else ! sprintf(tbuff, "%s%d%s%s", strdl, ival, strdl, flddl); ! insert_num; ! } else if (isfloat(xs[i], &dval)) { ! if (cvt_f) ! sprintf(tbuff, "%.16g%s", dval, flddl); else ! sprintf(tbuff, "%s%.16g%s%s", strdl, dval, strdl, flddl); ! insert_num; ! } else if (isstr(xs[i], &sval)) { ! qcnt = 0; ! p = sval; ! while (*p) ! if (!strncmp(p++, strdl, 1)) ++qcnt; ! mark = len; ! len += p - sval + qcnt + 3; /* strlen + double strdls + dquotes */ ! resize_str; ! p = sval; ! *t++ = *strdl; ! while (*t++ = *p) { ! if (!strncmp(p, strdl, 1)) ! *t++ = *p; ! ++p; } ! --t; ! *t++ = *strdl; ! *t++ = *flddl; ! } else { ! sprintf(errmsg, "Field %d: Invalid conversion type.", (i+1)); ! return mkapp(mksym(sym(csv_error)), mkstr(strdup(errmsg))); ! } } ! mark = len; #if defined (_WIN32) ! len += 2; ! resize_str; ! *(t-2) = '\r'; #else ! ++len; ! resize_str; #endif ! *(t-1) = '\n'; ! *t = 0; ! str = (char *)realloc(str, len); ! return mkstr(str); } Index: csv.q =================================================================== RCS file: /cvsroot/q-lang/q-csv/csv.q,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** csv.q 12 Jan 2008 04:30:49 -0000 1.4 --- csv.q 13 Jan 2008 17:27:14 -0000 1.5 *************** *** 21,151 **** that allow field delimiters and quote delimiters to be changed. */ ! private extern freadcsv_ ARGS; ! private extern fwritecsv_ ARGS REC; ! public freadcsv_data ARGS, freadcsv_string ARGS; ! /* _data variant converts fields to ints and floats on the fly ! _string variant makes all fields strings. ! ARGS is either a File or a tuple consisting of: ! (File, Field delimiter) or ! (File, Field delimiter, String delimiter). ! Returns a tuple of fields read. */ ! public fwritecsv_data ARGS REC, fwritecsv_string ARGS REC; ! /* _data variant converts fields to ints and floats on the fly ! _string variant writes all fields strings. ! ARGS is either a File or a tuple consisting of: ! (File, Field delimiter) or ! (File, Field delimiter, String delimiter) ! REC is a tuple of fields to be written. ! NOTE that REC may only consist of strings, ints, and floats. ! */ ! public freadfilecsv_data ARGS, freadfilecsv_string ARGS; ! /* _data variant converts fields to ints and floats on the fly ! _string variant makes all fields strings. ! ARGS is either a File or a tuple consisting of: ! (File, Field delimiter) or ! (File, Field delimiter, String delimiter). ! Returns a list where each record is a tuple of fields. */ ! public fwritefilecsv_data ARGS LIST, fwritefilecsv_string ARGS LIST; ! /* _data variant converts fields to ints and floats on the fly ! _string variant writes all fields as strings. ! ARGS is either a File or a tuple consisting of: ! (File, Field delimiter) or ! (File, Field delimiter, String delimiter). ! LIST is a list where each record is a tuple of fields. ! NOTE that REC may only consist of strings, ints, and floats. */ ! freadcsv_data F:File ! = freadcsv_ (true, F, ",", "\""); ! freadcsv_data (F:File, FieldDelim:String) ! = freadcsv_ (true, F, FieldDelim, "\""); freadcsv_data (F:File, FieldDelim:String, StrDelim:String) ! = freadcsv_ (true, F, FieldDelim, StrDelim); ! freadcsv_string F:File ! = freadcsv_ (false, F, ",", "\""); ! freadcsv_string (F:File, FieldDelim:String) ! = freadcsv_ (false, F, FieldDelim, "\""); ! freadcsv_string (F:File, FieldDelim:String, StrDelim:String) ! = freadcsv_ (false, F, FieldDelim, StrDelim); fwritecsv_data F:File Rec:Tuple ! = fwritecsv_ (true, F, ",", "\"") Rec; ! fwritecsv_data (F:File, FieldDelim:String) Rec:Tuple ! = fwritecsv_ (true, F, FieldDelim, "\"") Rec; fwritecsv_data (F:File, FieldDelim:String, StrDelim:String) Rec:Tuple ! = fwritecsv_ (true, F, FieldDelim, StrDelim) Rec; fwritecsv_string F:File Rec:Tuple ! = fwritecsv_ (false, F, ",", "\"") Rec; ! fwritecsv_string (F:File, FieldDelim:String) Rec:Tuple ! = fwritecsv_ (false, F, FieldDelim, "\"") Rec; fwritecsv_string (F:File, FieldDelim:String, StrDelim:String) Rec:Tuple ! = fwritecsv_ (false, F, FieldDelim, StrDelim) Rec; ! ! /* Only use the following functions if you KNOW the data files are small */ ! ! freadfilecsv_data F:File ! = [] if feof F; ! = [freadcsv_ (true, F, ",", "\"") ! | freadfilecsv_data F]; ! freadfilecsv_data (F:File, FieldDelim:String) ! = [] if feof F; ! = [freadcsv_ (true, F, FieldDelim, "\"") ! | freadfilecsv_data (F, FieldDelim)]; ! freadfilecsv_data (F:File, FieldDelim:String, StrDelim:String) ! = [] if feof F; ! = [freadcsv_ (true, F, FieldDelim, StrDelim) ! | freadfilecsv_data (F, FieldDelim, StrDelim)]; ! ! freadfilecsv_string F:File ! = [] if feof F; ! = [freadcsv_ (false, F, ",", "\"") ! | freadfilecsv_string F]; ! freadfilecsv_string (F:File, FieldDelim:String) ! = [] if feof F; ! = [freadcsv_ (false, F, FieldDelim, "\"") ! | freadfilecsv_string (F, FieldDelim)]; ! freadfilecsv_string (F:File, FieldDelim:String, StrDelim:String) ! = [] if feof F; ! = [freadcsv_ (false, F, FieldDelim, StrDelim) | ! freadfilecsv_string (F, FieldDelim, StrDelim)]; ! fwritefilecsv_data F:File L:List ! = do (fwritecsv_ (true, F, ",", "\"")) L; ! fwritefilecsv_data (F:File, FieldDelim:String) L:List ! = do (fwritecsv_ (true, F, FieldDelim, "\"")) L; ! fwritefilecsv_data (F:File, FieldDelim:String, StrDelim:String) L:List ! = do (fwritecsv_ (true, F, FieldDelim, StrDelim)) L; ! fwritefilecsv_string F:File L:List ! = do (fwritecsv_ (false, F, ",", "\"")) L; ! fwritefilecsv_string (F:File, FieldDelim:String) L:List ! = do (fwritecsv_ (false, F, FieldDelim, "\"")) L; ! fwritefilecsv_string (F:File, FieldDelim:String, StrDelim:String) L:List ! = do (fwritecsv_ (false, F, FieldDelim, StrDelim)) L; ! /* Primary interface functions. These are defined to be the _data variants by ! default, but you can change this using appropriate definitions in your ! program. */ ! public freadcsv ARGS, fwritecsv ARGS REC; ! /* freadcsv ARGS = freadcsv_data ARGS ! fwritecsv ARGS = fwritecsv_data ARGS REC */ ! public freadfilecsv ARGS, fwritefilecsv ARGS REC; ! /* freadfilecsv ARGS = freadfilecsv_data ARGS ! fwritefilecsv ARGS REC = fwritefilecsv_data ARGS REC */ ! @-0x80000000 ! freadcsv = freadcsv_data; ! freadfilecsv = freadfilecsv_data; ! fwritecsv = fwritecsv_data; ! fwritefilecsv = fwritefilecsv_data; ! @0 \ No newline at end of file --- 21,117 ---- that allow field delimiters and quote delimiters to be changed. */ ! public extern fread_csvstr FILE STRDELIM; ! /* Read a CSV record from a file (including embedded new lines). ! FILE: file to be read from ! STRDELIM: string delimiter used in the CSV format ! NOTE: fread_csvstr does not take into account badly formated records. ! csvstr_to_tuple is necessary for error checking. */ ! public extern tuple_to_csvstr ARGS REC; ! /* Convert a tuple (record) to CSV string ! ARGS: tuple (auto conversion flag, field delimiter, string delimiter) ! REC: tuple of fields to be converted to CSV format ! NOTES ! (1) REC must contain ONLY strings, integers, and floating point numbers. ! If a field is some other type, the 'csv_error MSG' rule is invoked. ! (2) When the auto conversion flag is false, ALL fields are strings. */ ! public extern csvstr_to_tuple ARGS STR; ! /* Convert CSV string to a tuple (record). ! ARGS: tuple (auto conversion flag, field delimiter, string delimiter) ! STR: tuple of fields to be converted to CSV format ! ! NOTES ! (1) A properly formated CSV string MUST end with a '\n' ! (2) When the auto conversion flag is false, All fields are strings. ! (3) The 'csv_error MSG' rule is invoked on improperly formated strings. */ ! public csv_error MSG; ! /* User may define csv_error for custom error handling. */ ! ! public freadcsv_data ARGS; ! /* Read one CSV record from the file with number conversion. */ ! ! freadcsv_data F:File ! = csvstr_to_tuple (true, ",", "\"") (fread_csvstr F "\""); freadcsv_data (F:File, FieldDelim:String, StrDelim:String) ! = csvstr_to_tuple (true, FieldDelim, StrDelim) (fread_csvstr F StrDelim); ! public freadcsv_string ARGS; ! /* Read one CSV record from the file without number conversion. */ ! ! freadcsv_string F:File ! = csvstr_to_tuple (false, "," "\"") (fread_csvstr F "\""); ! freadcsv_string_data (F:File, FieldDelim:String, StrDelim:String) ! = csvstr_to_tuple (false, "," "\"") (fread_csvstr F StrDelim); ! ! public fwritecsv_data FILE REC; ! /* Write one CSV record to a file with number conversion. */ fwritecsv_data F:File Rec:Tuple ! = fwrites F (tuple_to_csvstr (true, ",", "\"") Rec); fwritecsv_data (F:File, FieldDelim:String, StrDelim:String) Rec:Tuple ! = fwrites F (tuple_to_csvstr (true, FieldDelim, StrDelim) Rec); ! ! public fwritecsv_string FILE REC; ! /* Write one CSV record to a file without number conversion. */ fwritecsv_string F:File Rec:Tuple ! = fwrites F (tuple_to_csvstr (false, ",", "\"") Rec); fwritecsv_string (F:File, FieldDelim:String, StrDelim:String) Rec:Tuple ! = fwrites F (tuple_to_csvstr (false, FieldDelim, StrDelim) Rec); ! public freadcsvfile_data ARGS, freadcsvfile_string ARGS; ! /* Read an entire file of records into a list of tuples. */ ! freadcsvfile_data F:File ! = [] if feof F; ! = [freadscsv_data F | freadcsvfile_data F]; ! freadcsvfile_data (F:File, FieldDelim:String, StrDelim:String) ! = [] if feof F; ! = [freadscsv_data (F, FieldDelim, StrDelim) | freadcsvfile_data F]; ! freadcsvfile_string F:File ! = [] if feof F; ! = [freadscsv_string F | freadcsvfile_dara F]; ! freadcsvfile_string (F:File, FieldDelim:String, StrDelim:String) ! = [] if feof F; ! = [freadscsv_string (F, FieldDelim, StrDelim) | freadcsvfile_string F]; ! public fwritecsvfile_data FILE LIST, fwritefile_string ARGS; ! /* Write a list of tuples to a CSV formated file. */ ! fwritecsvfile_data F:File L:List ! = do (fwritecsv_data F) L; ! fwritecsvfile_data (F:File, FieldDelim:String, StrDelim:String) L:List ! = do (fwritecsv_data (F, FieldDelim, StrDelim)) L; ! fwritecsvfile_string F:File L:List ! = do (fwritecsv_string F) L; ! fwritecsvfile_string (F:File, FieldDelim:String, StrDelim:String) L:List ! = do (fwritecsv_string (F, FieldDelim, StrDelim)) L; \ No newline at end of file |