Skip to content

Instantly share code, notes, and snippets.

@noureddin
Created October 30, 2020 03:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save noureddin/42e06cc242cae42fda9e3369caa1df0c to your computer and use it in GitHub Desktop.
Save noureddin/42e06cc242cae42fda9e3369caa1df0c to your computer and use it in GitHub Desktop.
A simple, performant CSV to TSV converter.
// A simple, performant CSV to TSV converter.
// Roughly the same performance as `xsv fmt -t '\t'`
// if compiled with `-O1` or higher.
// Note: if the input doesn't end with '\n', this program will still
// work correctly but won't add a final '\n'. If it ends with '\n',
// the output will have it.
// Copyright 2020 Noureddin (github.com/noureddin).
// License: Creative Commons Zero (aka Public Domain).
#include <stdio.h> // getchar, putchar, fprintf
#include <stdbool.h> // bool, true, false
#include <stdlib.h> // exit
#define QUOTE '"'
#define FS ',' // input field separator
#define RS '\n' // input record separator
#define OFS '\t' // output field separator
#define ORS '\n' // output record separator
int main(void) {
int ch;
bool quoted;
bool field_start = true;
#define StartField() do { putchar(OFS); field_start = true; } while (0)
#define StartRecord() do { putchar(ORS); field_start = true; } while (0)
while ((ch = getchar()) != EOF) {
if (field_start) {
switch (ch) {
case FS: StartField(); break;
case RS: StartRecord(); break;
case QUOTE: quoted = true; field_start = false; break;
default: quoted = false; field_start = false; putchar(ch);
}
continue;
}
// if not field_start
switch (ch) {
case FS:
if (quoted)
putchar(ch);
else
StartField();
break;
case RS:
StartRecord();
break;
case QUOTE: {
int ch2 = getchar();
switch (ch2) {
case QUOTE: putchar(QUOTE); break;
case FS: StartField(); break;
case RS: StartRecord(); break;
case EOF: return 0;
default:
fprintf(stderr, "Unexpected sequence: %c%c\n", ch, ch2);
exit(2);
}
break;
}
default:
putchar(ch);
}
}
#undef StartField
#undef StartRecord
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment