diff options
| author | pepper <peppersclothescult@gmail.com> | 2015-01-19 00:02:46 -0800 |
|---|---|---|
| committer | pepper <peppersclothescult@gmail.com> | 2015-01-19 00:02:46 -0800 |
| commit | 760d4d5a0fc89e5b14681879577a80e79795e4a3 (patch) | |
| tree | 3698995f434a00a904f9fdff64a739eb21f53fdb /midicsv-1.1/csv.c | |
Diffstat (limited to 'midicsv-1.1/csv.c')
| -rw-r--r-- | midicsv-1.1/csv.c | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/midicsv-1.1/csv.c b/midicsv-1.1/csv.c new file mode 100644 index 0000000..ada7d75 --- /dev/null +++ b/midicsv-1.1/csv.c @@ -0,0 +1,146 @@ +/* + + Comma separated value database format scanner + + This function implements a somewhat extended flavour + of CSV. In addition to the standard quoted fields, + permitting embedded commas, with embedded quotes + represented as "", backslash escaped characters + expressed as three octal digits are also permitted, + with a double backslash representing an embedded + backslash. This is necessary to permit fields + which include end-of-line delimiters which would + otherwise truncate the record when it is read. + +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "csv.h" + +#define BufferInitial 256 /* Initial buffer size */ +#define BufferExpansion 1024 /* Buffer expansion increment */ + +#define EOS '\0' + +#define FALSE 0 +#define TRUE 1 + +static const char *csptr; /* CSV scan pointer */ + +/* CSVSCANINIT -- Initialise scanning of a CSV record. */ + +void CSVscanInit(const char *s) +{ + csptr = s; +} + +/* CSVSCANFIELD -- Scan next field from a CSV record. The actual + length of the field is placed in the + global variable CSVfieldLength. If the + field is not quoted, leading and trailing + spaces are discarded. + + The argument b_f is a pointer to a +*/ + +int CSVfieldLength = 0; /* Length of CSV field scanned */ + +#define f (*b_f) +#define flen (*b_flen) + +static void expand_buf(char **b_f, int *b_flen) +{ + if ((f == NULL) || (flen == 0)) { + f = (char *) malloc(BufferInitial); + if (f == NULL) { + fprintf(stderr, "Unable to allocate %d byte CSV field buffer.\n", BufferInitial); + abort(); + } + flen = BufferInitial; + } else { + flen += BufferExpansion; + f = (char *) realloc(f, flen); + if (f == NULL) { + fprintf(stderr, "Unable to expand CSV field buffer to %d bytes.\n", flen); + abort(); + } + } +} + +#define store(c) if (CSVfieldLength >= (flen - 1)) \ + { expand_buf(b_f, b_flen); } \ + f[CSVfieldLength] = c; \ + CSVfieldLength++; + +int CSVscanField(char **b_f, int *b_flen) +{ + int foundfield = FALSE, quoted = FALSE; + + CSVfieldLength = 0; + if (*csptr != EOS) { + foundfield = TRUE; + while ((*csptr != EOS) && isspace(*csptr)) { + csptr++; + } + if (*csptr == '"') { + quoted = TRUE; + csptr++; + while (*csptr != EOS) { + if (*csptr == '"') { + if (csptr[1] == '"') { + store('"'); + csptr += 2; + } else { + csptr++; + break; + } + } else if (*csptr == '\\') { + if (csptr[1] == '\\') { + store('\\'); + csptr += 2; + } else { + unsigned int v = 0; + int i; + + for (i = 0; i < 3; i++) { + csptr++; + if ((*csptr >= '0') && (*csptr <= '7')) { + v = (v << 3) | (*csptr - '0'); + } else { + csptr--; + } + } + csptr++; + store((char) v); + } + } else { + char c = *csptr++; + store(c); + } + } + } + while (*csptr != ',' && *csptr != EOS) { + char c = *csptr++; + store(c); + } + if (*csptr == ',') { + csptr++; + } + } + f[CSVfieldLength] = EOS; /* Append C string terminator */ + + /* If the field wasn't quoted, elide any trailing spaces. */ + + if (foundfield && !quoted) { + while (CSVfieldLength > 0 && isspace(f[CSVfieldLength - 1])) { + f[--CSVfieldLength] = EOS; + } + } + return foundfield; +} +#undef f +#undef flen |
