Initial commit
This commit is contained in:
commit
d2182a433c
9 changed files with 421 additions and 0 deletions
193
json.c
Normal file
193
json.c
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
#include "json.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define UNREACHABLE() assert(false)
|
||||
|
||||
Json json_init(FILE* stream, Whitespace whitespace)
|
||||
{
|
||||
return (Json){
|
||||
.stream = stream,
|
||||
.whitespace = whitespace,
|
||||
.indent_level = 0,
|
||||
.next_punctuation = BEGINNING,
|
||||
};
|
||||
}
|
||||
|
||||
void json_free(Json* json)
|
||||
{
|
||||
}
|
||||
|
||||
void begin_value(Json* json);
|
||||
void end_value(Json* json);
|
||||
void push_indentation(Json* json);
|
||||
void pop_indentation(Json* json);
|
||||
void indent(Json* json);
|
||||
|
||||
void json_begin_array(Json* json)
|
||||
{
|
||||
begin_value(json);
|
||||
putc('[', json->stream);
|
||||
push_indentation(json);
|
||||
json->next_punctuation = NONE;
|
||||
}
|
||||
|
||||
void json_end_array(Json* json)
|
||||
{
|
||||
pop_indentation(json);
|
||||
switch (json->next_punctuation) {
|
||||
case NONE:
|
||||
break;
|
||||
case COMMA:
|
||||
indent(json);
|
||||
break;
|
||||
case BEGINNING:
|
||||
case COLON:
|
||||
UNREACHABLE();
|
||||
}
|
||||
putc(']', json->stream);
|
||||
end_value(json);
|
||||
}
|
||||
|
||||
void json_begin_object(Json* json)
|
||||
{
|
||||
begin_value(json);
|
||||
putc('{', json->stream);
|
||||
push_indentation(json);
|
||||
json->next_punctuation = NONE;
|
||||
}
|
||||
|
||||
void json_end_object(Json* json)
|
||||
{
|
||||
pop_indentation(json);
|
||||
switch (json->next_punctuation) {
|
||||
case NONE:
|
||||
break;
|
||||
case COMMA:
|
||||
indent(json);
|
||||
break;
|
||||
case BEGINNING:
|
||||
case COLON:
|
||||
UNREACHABLE();
|
||||
}
|
||||
putc('}', json->stream);
|
||||
end_value(json);
|
||||
}
|
||||
|
||||
void json_add_object_field(Json* json, const char* key)
|
||||
{
|
||||
begin_value(json);
|
||||
fprintf(json->stream, "\"%s\"", key);
|
||||
json->next_punctuation = COLON;
|
||||
}
|
||||
|
||||
void json_add_string(Json* json, const char* value)
|
||||
{
|
||||
begin_value(json);
|
||||
fprintf(json->stream, "\"%s\"", value);
|
||||
end_value(json);
|
||||
}
|
||||
|
||||
void json_add_long(Json* json, long value)
|
||||
{
|
||||
begin_value(json);
|
||||
fprintf(json->stream, "%ld", value);
|
||||
end_value(json);
|
||||
}
|
||||
|
||||
void json_add_double(Json* json, double value)
|
||||
{
|
||||
begin_value(json);
|
||||
fprintf(json->stream, "%f", value);
|
||||
end_value(json);
|
||||
}
|
||||
|
||||
void json_add_bool(Json* json, bool value)
|
||||
{
|
||||
begin_value(json);
|
||||
const char* s;
|
||||
if (value) {
|
||||
s = "true";
|
||||
} else {
|
||||
s = "false";
|
||||
}
|
||||
fputs(s, json->stream);
|
||||
end_value(json);
|
||||
}
|
||||
|
||||
void json_add_null(Json* json)
|
||||
{
|
||||
begin_value(json);
|
||||
fputs("null", json->stream);
|
||||
end_value(json);
|
||||
}
|
||||
|
||||
void begin_value(Json* json)
|
||||
{
|
||||
switch (json->next_punctuation) {
|
||||
case BEGINNING:
|
||||
break;
|
||||
case NONE:
|
||||
indent(json);
|
||||
break;
|
||||
case COMMA:
|
||||
fputc(',', json->stream);
|
||||
indent(json);
|
||||
break;
|
||||
case COLON:
|
||||
putc(':', json->stream);
|
||||
if (json->whitespace != MINIFIED) {
|
||||
fputc(' ', json->stream);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void end_value(Json* json)
|
||||
{
|
||||
json->next_punctuation = COMMA;
|
||||
}
|
||||
|
||||
void push_indentation(Json* json)
|
||||
{
|
||||
json->indent_level += 1;
|
||||
}
|
||||
|
||||
void pop_indentation(Json* json)
|
||||
{
|
||||
json->indent_level -= 1;
|
||||
}
|
||||
|
||||
void indent(Json* json)
|
||||
{
|
||||
char indent_char = ' ';
|
||||
int n;
|
||||
switch (json->whitespace) {
|
||||
case MINIFIED:
|
||||
return;
|
||||
case INDENT_1:
|
||||
n = 1 * json->indent_level;
|
||||
break;
|
||||
case INDENT_2:
|
||||
n = 2 * json->indent_level;
|
||||
break;
|
||||
case INDENT_3:
|
||||
n = 3 * json->indent_level;
|
||||
break;
|
||||
case INDENT_4:
|
||||
n = 4 * json->indent_level;
|
||||
break;
|
||||
case INDENT_8:
|
||||
n = 8 * json->indent_level;
|
||||
break;
|
||||
case INDENT_TAB:
|
||||
indent_char = '\t';
|
||||
n = json->indent_level;
|
||||
break;
|
||||
}
|
||||
putc('\n', json->stream);
|
||||
for (int i = 0; i < n; i++) {
|
||||
putc(indent_char, json->stream);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue