summaryrefslogtreecommitdiffstats
path: root/src/csv.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/csv.h')
-rw-r--r--src/csv.h45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/csv.h b/src/csv.h
new file mode 100644
index 0000000..90a9d83
--- /dev/null
+++ b/src/csv.h
@@ -0,0 +1,45 @@
+/**
+ * @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 <stddef.h>
+
+/** 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