No description
Find a file
2025-11-29 07:27:16 -08:00
.gitignore Initial commit 2021-11-10 22:30:06 -08:00
ccsv.h license added 2025-11-29 07:26:38 -08:00
LICENSE license added 2025-11-29 07:26:38 -08:00
README.md Update README.md 2025-09-08 14:53:55 -07:00
t.c fixing quote trimming bug 2021-11-11 12:37:50 -08:00

ccsv.h — Header-only CSV Line Parser

A lightweight, header-only CSV line parser compliant with RFC 4180.

  • No heap allocations (caller manages buffers).
  • Parses one CSV line in place.
  • Works with configurable delimiters.
  • Quoted fields handled per RFC 4180.

Data Structures

struct ccsv
{
    char *line;   /* Current parse position, updated by parser */
    char delim;   /* Field delimiter, usually ',' or ';' */
};

Macros

ccsv_init_ex(_csv, _ln, _dlm)

Initialize a parser with a line and a custom delimiter.

  • _csv: pointer to a struct ccsv
  • _ln: pointer to a mutable C string containing the CSV line (will be modified in place)
  • _dlm: delimiter character (e.g. ',' or ';')

ccsv_init(_csv, _ln)

Initialize a parser with a line and comma as the delimiter.

  • _csv: pointer to a struct ccsv
  • _ln: pointer to a mutable C string containing the CSV line

Functions

char *ccsv_nextfield(struct ccsv *csv, char *type)

Return the next field from the CSV line. Fields are null-terminated in place.

  • csv: previously initialized parser instance

  • type: optional output, receives

    • '"' if the field was quoted
    • delimiter character if unquoted

Returns:

  • Pointer to the start of the next field (C string)
  • NULL if there are no more fields or an error occurred

Notes:

  • Whitespace outside quotes is trimmed.
  • Escaped quotes ("") inside quoted fields are handled.
  • The function modifies the input line buffer (fields are separated by '\0').

Example

#include <stdio.h>
#include <stdlib.h>
#include "ccsv.h"

int main(void)
{
    const char *line = "  foo,  \"bar\" , \"b\"\",baz\"  ";
    struct ccsv c;
    char *f, type;
    char *copy = strdup(line);

    ccsv_init(&c, copy);

    while ((f = ccsv_nextfield(&c, &type)) != NULL)
    {
        printf("%s field: '%s'\n", type == '"' ? "quoted" : "normal", f);
    }

    free(copy);
    return 0;
}

Output:

normal field: 'foo'
quoted field: 'bar'
quoted field: 'b"",baz'

Limitations

  • Parses one line at a time; caller must split multi-line CSV input.
  • No dynamic allocation inside the parser; caller must provide mutable buffers.
  • Not thread-safe if you try to reuse the same struct ccsv across threads without protection.