From 9ee82d9d744de52916817412318f43f26960d719 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Tue, 21 Jan 2025 19:41:00 -0800 Subject: get-csv: rewrite in C. * autload.c (csv_set_entries, csv_instantiate): Functions removed. (autoload_init): Autoload registration for stdlib/csv removed. * stdlib/csv.tl: File removed. * stream.c (get_csv): New function. (stream_init): Register get-csv intrinsic. * stream.h (get_csv): Declared. --- stream.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) (limited to 'stream.c') diff --git a/stream.c b/stream.c index 51b8c4d9..8b9b2f60 100644 --- a/stream.c +++ b/stream.c @@ -5422,6 +5422,83 @@ val make_byte_input_stream(val obj) } } +val get_csv(val source_opt) +{ + val source = if3(missingp(source_opt), + std_input, + if3(stringp(source_opt), + make_string_input_stream(source_opt), + source_opt)); + val record = vector(zero, nil); + val field = mkstring(zero, chr(' ')); + enum { rfield, qfield, quot } state = rfield; + int done = 0; + + while (!done) { + val ch = get_char(source); + + if (ch == chr('\r')) { + val ch2 = get_char(source); + if (ch2 == chr('\n')) + ch = ch2; + else if (ch2) + unget_char(ch2, source); + } + + switch (state) { + case rfield: + if (ch == chr('\n')) { + vec_push(record, field); + done = 1; + } else if (ch == chr(',')) { + vec_push(record, field); + field = mkstring(zero, chr(' ')); + } else if (ch == chr('"')) { + if (empty(field)) + state = qfield; + else + string_extend(field, ch, nil); + } else if (ch == nil) { + vec_push(record, field); + done = 1; + } else { + string_extend(field, ch, nil); + } + break; + case qfield: + if (ch == chr('"')) { + state = quot; + } else if (ch == nil) { + vec_push(record, field); + done = 1; + } else { + string_extend(field, ch, nil); + } + break; + case quot: + if (ch == chr(',')) { + vec_push(record, field); + field = mkstring(zero, chr(' ')); + state = rfield; + } else if (ch == chr('"')) { + string_extend(field, ch, nil); + state = qfield; + } else if (ch == chr('\n')) { + vec_push(record, field); + done = 1; + } else if (ch == nil) { + vec_push(record, field); + done = 1; + } else { + string_extend(field, ch, nil); + state = rfield; + } + } + } + + return record; +} + val tmpfile_wrap(void) { val self = lit("tmpfile"); @@ -5697,6 +5774,7 @@ void stream_init(void) reg_varl(intern(lit("indent-data"), user_package), num_fast(indent_data)); reg_varl(intern(lit("indent-code"), user_package), num_fast(indent_code)); reg_varl(intern(lit("indent-foff"), user_package), num_fast(indent_foff)); + reg_fun(intern(lit("get-csv"), user_package), func_n1o(get_csv, 0)); reg_fun(intern(lit("tmpfile"), user_package), func_n0(tmpfile_wrap)); #if HAVE_MKDTEMP reg_fun(intern(lit("mkdtemp"), user_package), func_n1(mkdtemp_wrap)); -- cgit v1.2.3