// ---------------------------------------------------------------- static lrec_t* lrec_reader_mmap_csv_process(void* pvstate, void* pvhandle, context_t* pctx) { lrec_reader_mmap_csv_state_t* pstate = pvstate; file_reader_mmap_state_t* phandle = pvhandle; if (pstate->expect_header_line_next) { if (!lrec_reader_mmap_csv_get_fields(pstate, pstate->pfields, phandle)) return NULL; pstate->ilno++; slls_t* pheader_fields = slls_alloc(); int i = 0; for (rsllse_t* pe = pstate->pfields->phead; i < pstate->pfields->length && pe != NULL; pe = pe->pnext, i++) { if (*pe->value == 0) { fprintf(stderr, "%s: unacceptable empty CSV key at file \"%s\" line %lld.\n", MLR_GLOBALS.argv0, pctx->filename, pstate->ilno); exit(1); } // Transfer pointer-free responsibility from the rslls to the // header fields in the header keeper slls_append(pheader_fields, pe->value, pe->free_flag); pe->free_flag = 0; } rslls_reset(pstate->pfields); pstate->pheader_keeper = lhmslv_get(pstate->pheader_keepers, pheader_fields); if (pstate->pheader_keeper == NULL) { pstate->pheader_keeper = header_keeper_alloc(NULL, pheader_fields); lhmslv_put(pstate->pheader_keepers, pheader_fields, pstate->pheader_keeper, NO_FREE); // freed by header-keeper } else { // Re-use the header-keeper in the header cache slls_free(pheader_fields); } pstate->expect_header_line_next = FALSE; } int rc = lrec_reader_mmap_csv_get_fields(pstate, pstate->pfields, phandle); pstate->ilno++; if (rc == FALSE) // EOF return NULL; else { lrec_t* prec = pstate->use_implicit_header ? paste_indices_and_data(pstate, pstate->pfields, pctx) : paste_header_and_data(pstate, pstate->pfields, pctx); rslls_reset(pstate->pfields); return prec; } }
// ---------------------------------------------------------------- static lrec_t* lrec_reader_stdio_csv_process(void* pvstate, void* pvhandle, context_t* pctx) { lrec_reader_stdio_csv_state_t* pstate = pvstate; // Ingest the next header line, if expected if (pstate->expect_header_line_next) { while (TRUE) { if (!lrec_reader_stdio_csv_get_fields(pstate, pstate->pfields, pctx, TRUE)) return NULL; pstate->ilno++; // We check for comments here rather than within the parser since it's important // for users to be able to comment out lines containing double-quoted newlines. if (pstate->comment_string != NULL && pstate->pfields->phead != NULL) { if (streqn(pstate->pfields->phead->value, pstate->comment_string, pstate->comment_string_length)) { if (pstate->comment_handling == PASS_COMMENTS) { int i = 0; for ( rsllse_t* pe = pstate->pfields->phead; i < pstate->pfields->length && pe != NULL; pe = pe->pnext, i++) { if (i > 0) fputs(pstate->ifs, stdout); fputs(pe->value, stdout); } if (pstate->do_auto_line_term) { fputs(pctx->auto_line_term, stdout); } else { fputs(pstate->irs, stdout); } } rslls_reset(pstate->pfields); continue; } } slls_t* pheader_fields = slls_alloc(); int i = 0; for (rsllse_t* pe = pstate->pfields->phead; i < pstate->pfields->length && pe != NULL; pe = pe->pnext) { if (*pe->value == 0) { fprintf(stderr, "%s: unacceptable empty CSV key at file \"%s\" line %lld.\n", MLR_GLOBALS.bargv0, pctx->filename, pstate->ilno); exit(1); } // Transfer pointer-free responsibility from the rslls to the // header fields in the header keeper slls_append(pheader_fields, pe->value, pe->free_flag); pe->free_flag = 0; } rslls_reset(pstate->pfields); pstate->pheader_keeper = lhmslv_get(pstate->pheader_keepers, pheader_fields); if (pstate->pheader_keeper == NULL) { pstate->pheader_keeper = header_keeper_alloc(NULL, pheader_fields); lhmslv_put(pstate->pheader_keepers, pheader_fields, pstate->pheader_keeper, NO_FREE); // freed by header-keeper } else { // Re-use the header-keeper in the header cache slls_free(pheader_fields); } pstate->expect_header_line_next = FALSE; break; } } // Ingest the next data line, if expected while (TRUE) { int rc = lrec_reader_stdio_csv_get_fields(pstate, pstate->pfields, pctx, FALSE); pstate->ilno++; if (rc == FALSE) // EOF return NULL; // We check for comments here rather than within the parser since it's important // for users to be able to comment out lines containing double-quoted newlines. if (pstate->comment_string != NULL && pstate->pfields->phead != NULL) { if (streqn(pstate->pfields->phead->value, pstate->comment_string, pstate->comment_string_length)) { if (pstate->comment_handling == PASS_COMMENTS) { int i = 0; for ( rsllse_t* pe = pstate->pfields->phead; i < pstate->pfields->length && pe != NULL; pe = pe->pnext, i++) { if (i > 0) fputs(pstate->ifs, stdout); fputs(pe->value, stdout); } if (pstate->do_auto_line_term) { fputs(pctx->auto_line_term, stdout); } else { fputs(pstate->irs, stdout); } } rslls_reset(pstate->pfields); continue; } } lrec_t* prec = pstate->use_implicit_header ? paste_indices_and_data(pstate, pstate->pfields, pctx) : paste_header_and_data(pstate, pstate->pfields, pctx); rslls_reset(pstate->pfields); return prec; } }