/** * @file csv.h * @brief Minimal RFC 4180 CSV reader, internal to this library. * * The batch endpoint answers `text/csv`, and its values may contain commas and * are then double-quoted with `""` escaping. Splitting on commas would corrupt * exactly the street names most likely to matter, so this reads the real * grammar: quoted fields, embedded commas, embedded newlines, CRLF or LF line * endings, and a leading UTF-8 BOM. */ #ifndef CEPIS_CSV_H #define CEPIS_CSV_H #include /** One parsed record. Owns its fields. */ typedef struct csv_row { char **fields; size_t count; } csv_row_t; typedef struct csv_reader csv_reader_t; /** * @brief Start reading @p len bytes of CSV. * @return A reader borrowing @p data, or `NULL` on allocation failure. @p data * must outlive the reader. */ csv_reader_t *csv_reader_new(const char *data, size_t len); /** * @brief Read the next record into @p out. * @return 1 when a record was read, 0 at end of input, -1 on a malformed * record or allocation failure. @p out is only valid after 1, and the * caller releases it with ::csv_row_free. */ int csv_reader_next(csv_reader_t *reader, csv_row_t *out); /** @brief Release a record's fields and zero it. `NULL` is ignored. */ void csv_row_free(csv_row_t *row); /** @brief Release a reader. `NULL` is ignored. */ void csv_reader_free(csv_reader_t *reader); #endif