From 5da855c331d20614c004f366ffcb571d9e6861c7 Mon Sep 17 00:00:00 2001 From: John Kerl Date: Sat, 22 Aug 2015 21:08:49 -0400 Subject: [PATCH] [csv iterate] string-builder iterate --- c/csv-rfc.txt | 9 +++++++++ c/lib/string_builder.c | 19 ++++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/c/csv-rfc.txt b/c/csv-rfc.txt index dc546678c..ba20be10c 100644 --- a/c/csv-rfc.txt +++ b/c/csv-rfc.txt @@ -1,6 +1,13 @@ + ================================================================ --> parser option: write a grammar like the below. be careful to preserve the streaming property! +--> I don't see a way to line-at-a-time it in the formal grammar. + Other option is to find end of line via string arithmetic, + then pass that (null-terminated) string to the parser. But + correctly determining EOL in the presence of double-quote + semantics *is* the problem; nothing interesting left for the + parser to do. --> state-machine option: * each field either does or does not begin & end w/ " @@ -24,6 +31,8 @@ public fcn append_char, public fcn append_string, private fcn realloc resizing with minimal copy, public fcn zterm & produce. +================================================================ +Offlineable (subway-tunnelable) excerpt from https://tools.ietf.org/html/rfc4180 ================================================================ Definition of the CSV Format diff --git a/c/lib/string_builder.c b/c/lib/string_builder.c index 099c653c0..c7846237b 100644 --- a/c/lib/string_builder.c +++ b/c/lib/string_builder.c @@ -4,14 +4,10 @@ #include "../lib/mlrutil.h" #include "../lib/mlr_globals.h" +// Private method: static void sb_enlarge(string_builder_t* psb); -// typedef struct _string_builder_t { -// int used_length; -// int alloc_length; -// char* buffer; -// } string_builder_t; - +// ---------------------------------------------------------------- void sb_init(string_builder_t* psb, int alloc_length) { if (alloc_length < 1) { fprintf(stderr, "%s: string_builder alloc_length must be >= 1; got %d.\n", @@ -23,26 +19,31 @@ void sb_init(string_builder_t* psb, int alloc_length) { psb->buffer = mlr_malloc_or_die(alloc_length); // xxx malloc ... } +// ---------------------------------------------------------------- void sb_append_char(string_builder_t* psb, char c) { if (psb->used_length >= psb->alloc_length) sb_enlarge(psb); psb->buffer[psb->used_length++] = c; } +// ---------------------------------------------------------------- void sb_append_string(string_builder_t* psb, char* s) { for (char* p = s; *p; p++) sb_append_char(psb, *p); } +// ---------------------------------------------------------------- +// Keep and reuse the internal buffer. Allocate to the caller only +// the size needed. char* sb_finish(string_builder_t* psb) { sb_append_char(psb, '\0'); - char* rv = psb->buffer; + char* rv = mlr_malloc_or_die(psb->used_length); + memcpy(rv, psb->buffer, psb->used_length); psb->used_length = 0; - psb->alloc_length = 0; - psb->buffer = NULL; return rv; } +// ---------------------------------------------------------------- static void sb_enlarge(string_builder_t* psb) { int new_alloc_length = psb->alloc_length * 2; char* new_buffer = mlr_malloc_or_die(new_alloc_length);