From 31540ce793f1aa551e1df3054f37fb3221618361 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Fri, 24 Jan 2025 20:49:52 -0800 Subject: New functions for producing CSV. * stream.c (put_csv, tocsv): New functions. (stream_init): put-csv and tocsv intrinsics registered. * stream.h (put_csv, tocsv): Declared. * tests/010/csv.tl (mtest-pcsv): New macro. New test cases. * txr.1: Documented. --- stream.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'stream.c') diff --git a/stream.c b/stream.c index 421b70eb..7701ba39 100644 --- a/stream.c +++ b/stream.c @@ -5506,6 +5506,46 @@ val get_csv(val source_opt) return record; } +val put_csv(val record, val stream_in) +{ + val self = lit("put-csv"); + val dest = if3(missingp(stream_in), std_output, stream_in); + seq_iter_t rec_iter; + val field; + int comma = 0; + + seq_iter_init(self, &rec_iter, record); + + while (seq_get(&rec_iter, &field)) { + val str = tostringp(field); + if (comma) + put_char(chr(','), dest); + comma = 1; + if (find(chr('"'), str, nil, nil)) { + put_char(chr('"'), dest); + put_string(str_esc(lit("\""), chr('"'), str), dest); + put_char(chr('"'), dest); + } else if (break_str(str, lit(",\n\r"))) { + put_char(chr('"'), dest); + put_string(str, dest); + put_char(chr('"'), dest); + } else { + put_string(str, dest); + } + } + + put_char(chr('\n'), dest); + + return nil; +} + +val tocsv(val record) +{ + val ss = make_string_output_stream(); + put_csv(record, ss); + return get_string_from_stream(ss); +} + val tmpfile_wrap(void) { val self = lit("tmpfile"); @@ -5782,6 +5822,8 @@ void stream_init(void) 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("put-csv"), user_package), func_n2o(put_csv, 1)); + reg_fun(intern(lit("tocsv"), user_package), func_n1(tocsv)); 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