I am writing simple formatter for valid JSON. Is reads JSON data from stdin and writes formatted output to stdout. Goals: - given valid input produce valid formatted JSON output - constant memory usage - minimal viable program (smallest program that solves a particular problem) - feature free - easy to read and understand - be C99 compatible Non-goals: - validating JSON - handling arguments I am not aiming JSON validation right now (as said "formatter for valid JSON"). I tried adding arguments (like setting placeholder string with `-p`) but faced several issues: a) unclear what arguments must be implemented and b) I don't feel comfortable yet writing argument parsing code. So I skipped this for now. File in GitHub: https://github.com/sineemore/juu/blob/master/juu.c #include <stdio.h> #include <stdlib.h> /* EXIT_SUCCESS */ #define BUF_SIZE (1024 * 4) int main(int argc, char **argv) { char buf[BUF_SIZE]; const char placeholder[] = " "; unsigned int indent = 0; unsigned int i = 0; unsigned int k = 0; char is_string = 0; char escaped = 0; char ch; size_t n; while (0 < (n = fread(&buf, sizeof(char), BUF_SIZE, stdin))) { for (k = 0; k < n; k++) { ch = buf[k]; if (is_string) { /* Inside quoted string */ putchar(ch); if (! escaped) { if (ch == '"') { /* Unescaped quote, string just ended */ is_string = 0; } else if (ch == '\\') { escaped = 1; } } else { escaped = 0; } continue; } switch (ch) { case ' ': case '\t': case '\n': case '\r': /* Ignoring original formatting */ break; case '{': case '[': putchar(ch); putchar('\n'); i = ++indent; while (i-- > 0) fputs(placeholder, stdout); break; case '}': case ']': putchar('\n'); i = --indent; while (i-- > 0) fputs(placeholder, stdout); putchar(ch); if (indent == 0) putchar('\n'); break; case ',': putchar(','); putchar('\n'); i = indent; while (i-- > 0) fputs(placeholder, stdout); break; case ':': putchar(':'); putchar(' '); break; case '"': /* String/property key start, see if clause on top (line 20) */ putchar('"'); is_string = 1; break; default: /* Numbers, true, false, null */ putchar(ch); break; } } } return EXIT_SUCCESS; }