diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2025-01-24 20:49:52 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2025-01-24 20:49:52 -0800 |
commit | 31540ce793f1aa551e1df3054f37fb3221618361 (patch) | |
tree | cecace480fad4edf6c08e8028bf8043c61103ed9 /stream.c | |
parent | af458b10e3bc6709e68ef7d0ca1d2aabbeada414 (diff) | |
download | txr-31540ce793f1aa551e1df3054f37fb3221618361.tar.gz txr-31540ce793f1aa551e1df3054f37fb3221618361.tar.bz2 txr-31540ce793f1aa551e1df3054f37fb3221618361.zip |
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.
Diffstat (limited to 'stream.c')
-rw-r--r-- | stream.c | 42 |
1 files changed, 42 insertions, 0 deletions
@@ -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)); |