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:

1. unclear what arguments must be implemented
2. I don't feel comfortable yet writing argument parsing code. 

*So I skipped these 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;
    }