Created
June 24, 2024 16:38
-
-
Save ShawSumma/07543e222dba8c501250726a1d1edb0c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stddef.h> | |
#include <stdbool.h> | |
#include <stdlib.h> | |
#include <ctype.h> | |
struct json_array_t; | |
typedef struct json_array_t json_array_t; | |
struct json_object_t; | |
typedef struct json_object_t json_object_t; | |
struct json_value_t; | |
typedef struct json_value_t json_value_t; | |
struct json_array_t { | |
size_t alloc; | |
size_t len; | |
json_value_t *data; | |
}; | |
struct json_object_t { | |
size_t alloc; | |
size_t len; | |
json_value_t *keys; | |
json_value_t *values; | |
}; | |
struct json_value_t { | |
union { | |
bool boolean; | |
double number; | |
const char *string; | |
json_array_t *array; | |
json_object_t *object; | |
}; | |
enum { | |
JSON_INVALID, | |
JSON_NULL, | |
JSON_BOOLEAN, | |
JSON_NUMBER, | |
JSON_STRING, | |
JSON_ARRAY, | |
JSON_OBJECT, | |
} type; | |
}; | |
void file_trim(FILE *file) { | |
while (true) { | |
char c = fgetc(file); | |
if (!isspace(c)) { | |
ungetc(c, file); | |
break; | |
} | |
} | |
} | |
json_value_t read_json(FILE *file) { | |
file_trim(file); | |
char c = fgetc(file); | |
switch (c) { | |
case 'f': { | |
if (fgetc(file) == 'a' && fgetc(file) == 'l' && fgetc(file) == 's' && fgetc(file) == 'e') { | |
return (json_value_t) { | |
.type = JSON_BOOLEAN, | |
.boolean = false, | |
}; | |
} | |
} | |
case 't': { | |
if (fgetc(file) == 'r' && fgetc(file) == 'u' && fgetc(file) == 'e') { | |
return (json_value_t) { | |
.type = JSON_BOOLEAN, | |
.boolean = true, | |
}; | |
} | |
} | |
case '"': { | |
size_t alloc = 0; | |
size_t len = 0; | |
char *string = NULL; | |
while (true) { | |
char c = fgetc(file); | |
if (c == '"') { | |
break; | |
} | |
if (len + 1 >= alloc) { | |
alloc = (len + 1) * 2; | |
string = realloc(string, sizeof(char) * alloc); | |
} | |
string[len++] = c; | |
} | |
return (json_value_t) { | |
.type = JSON_STRING, | |
.string = string, | |
}; | |
} | |
case '[': { | |
ungetc(c, file); | |
json_array_t *array = malloc(sizeof(json_array_t)); | |
*array = (json_array_t) {0}; | |
while (true) { | |
file_trim(file); | |
char last = fgetc(file); | |
if (last == ']') { | |
break; | |
} | |
json_value_t entry = read_json(file); | |
if (array->len + 1 >= array->alloc) { | |
array->alloc = (array->len + 1) * 2; | |
array->data = realloc(array->data, sizeof(json_value_t) * array->alloc); | |
} | |
array->data[array->len++] = entry; | |
} | |
return (json_value_t) { | |
.type = JSON_ARRAY, | |
.array = array, | |
}; | |
} | |
default: { | |
ungetc(c, file); | |
if ('0' <= c && c <= '9') { | |
double number; | |
fscanf(file, "%lf", &number); | |
return (json_value_t) { | |
.type = JSON_NUMBER, | |
.number = number, | |
}; | |
} | |
break; | |
} | |
} | |
return (json_value_t) { | |
.type = JSON_INVALID, | |
}; | |
} | |
void write_json(FILE *out, json_value_t value) { | |
switch (value.type) { | |
case JSON_INVALID: { | |
fprintf(out, "ERROR\n"); | |
break; | |
} | |
case JSON_NULL: { | |
fprintf(out, "null"); | |
break; | |
} | |
case JSON_BOOLEAN: { | |
if (value.boolean) { | |
fprintf(out, "true"); | |
} else { | |
fprintf(out, "false"); | |
} | |
break; | |
} | |
case JSON_NUMBER: { | |
fprintf(out, "%.17g", value.number); | |
break; | |
} | |
case JSON_STRING: { | |
fprintf(out, "\"%s\"", value.string); | |
break; | |
} | |
case JSON_ARRAY: { | |
fprintf(out, "["); | |
for (size_t i = 0; i < value.array->len; i++) { | |
if (i != 0) { | |
fprintf(out, ","); | |
} | |
write_json(out, value.array->data[i]); | |
} | |
fprintf(out, "]"); | |
break; | |
} | |
case JSON_OBJECT: { | |
fprintf(out, "OBJECT\n"); | |
break; | |
} | |
} | |
} | |
int main() { | |
FILE *in_file = fopen("in.json", "r"); | |
json_value_t value = read_json(in_file); | |
fclose(in_file); | |
FILE *out_file = fopen("out.json", "w"); | |
write_json(out_file, value); | |
fclose(out_file); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment