I once (maybe a long time ago?) made a parser for JSON by:
1. Reading the entire file into RAM.
2. Providing a `const char *get_value(const char *jstring, const char *path, ...)` function with a NULL-terminated parameter list that would return the position of the value of the key at the specified path.
3. Providing a `copy_value(const char *position)` function to copy the value at the specified position.
Slow? Yup!
But, it was easy and safe[1] and used absolutely minimal RAM![2]. The recursive nature of the JSON tree also allowed the caller to use a returned value from `get_value` as the `jstring` argument in further calls to `get_value`.
I might still have a fork of it lying around somewhere.
[1] "Safe" meaning "Caller had to check for NULL return values, and ensure that NULL terminated the parameter list".
[2] GCC with `-O2` and above does proper TCO, eliminating unbounded stack growth.
1. Reading the entire file into RAM.
2. Providing a `const char *get_value(const char *jstring, const char *path, ...)` function with a NULL-terminated parameter list that would return the position of the value of the key at the specified path.
3. Providing a `copy_value(const char *position)` function to copy the value at the specified position.
Slow? Yup!
But, it was easy and safe[1] and used absolutely minimal RAM![2]. The recursive nature of the JSON tree also allowed the caller to use a returned value from `get_value` as the `jstring` argument in further calls to `get_value`.
I might still have a fork of it lying around somewhere.
[1] "Safe" meaning "Caller had to check for NULL return values, and ensure that NULL terminated the parameter list".
[2] GCC with `-O2` and above does proper TCO, eliminating unbounded stack growth.