dfsch_strbuf_t* dfsch_port_readline(dfsch_object_t* port){ int ch; char* buf; size_t buflen; size_t len; buflen = 128; len = 0; buf = GC_MALLOC_ATOMIC(buflen); dfsch_port_batch_read_start(port); DFSCH_UNWIND { while (1){ ch = dfsch_port_batch_read(port); if (ch == -1){ break; } if (buflen <= len){ buflen *= 2; buf = GC_REALLOC(buf, buflen); } buf[len] = ch; len++; if (ch == '\n'){ break; } } } DFSCH_PROTECT { dfsch_port_batch_read_end(port); } DFSCH_PROTECT_END; if (len == 0){ return NULL; } return dfsch_strbuf_create(buf, len); }
dfsch_object_t* dfsch_csv_read_line(dfsch_object_t* port, dfsch_csv_params_t* params){ char ch; dfsch_object_t* ret = NULL; dfsch_list_collector_t* lc = NULL; partial_string_t ps; if (!params){ params = &default_params; } DFSCH_UNWIND { dfsch_port_batch_read_start(port); start: ch = dfsch_port_batch_read(port); if (ch != -1) { lc = dfsch_make_list_collector(); } else { goto out; } ps_init(&ps); goto field_dispatch; field: ch = dfsch_port_batch_read(port); field_dispatch: if (ch == params->quote){ goto quoted; } else if (ch == params->delim){ dfsch_list_collect(lc, dfsch_make_string_buf(ps.buf, ps.ptr)); ps_init(&ps); } else if (ch == -1 || ch == '\n'){ dfsch_list_collect(lc, dfsch_make_string_buf(ps.buf, ps.ptr)); goto out; } else if (ch == params->escape){ ch = dfsch_port_batch_read(port); if (ch == -1){ dfsch_error("Unexpected end of file", port); } ps_append(&ps, ch); } else { ps_append(&ps, ch); } goto field; quoted: ch = dfsch_port_batch_read(port); if (ch == params->quote){ ch = dfsch_port_batch_read(port); if (ch != params->quote){ goto field_dispatch; } else { ps_append(&ps, ch); } } else if (ch == params->escape){ ch = dfsch_port_batch_read(port); if (ch == -1){ dfsch_error("Unexpected end of file", port); } ps_append(&ps, ch); } else { if (ch == -1){ dfsch_error("Unexpected end of file", port); } ps_append(&ps, ch); } goto quoted; out: if (lc){ ret = dfsch_list_2_vector(dfsch_collected_list(lc)); } else { ret = NULL; } } DFSCH_PROTECT { dfsch_port_batch_read_end(port); } DFSCH_PROTECT_END; return ret; }