2023-11-25 02:35:22 +00:00
|
|
|
#include "parser.h"
|
|
|
|
|
2023-11-23 20:31:54 +00:00
|
|
|
#include <assert.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include "path.h"
|
|
|
|
|
2023-11-25 16:15:30 +00:00
|
|
|
static struct Error *find_spec_json(
|
|
|
|
const struct Config *const config, FILE **handle
|
|
|
|
) {
|
2023-11-23 20:31:54 +00:00
|
|
|
const char *segments[] = {config->root_dir, config->target, "spec.json"};
|
|
|
|
char *filepath =
|
|
|
|
join_path_segments(sizeof(segments) / sizeof(char *), segments);
|
|
|
|
|
2023-11-25 16:15:30 +00:00
|
|
|
struct Error *error = 0;
|
2023-11-23 20:31:54 +00:00
|
|
|
// It is ok if the file does not exist. It is not ok if we couldn't open the
|
|
|
|
// file for any other reason.
|
|
|
|
*handle = fopen(filepath, "r");
|
|
|
|
if (!*handle && errno != ENOENT) {
|
2023-11-25 16:15:30 +00:00
|
|
|
error = ERROR_NEW(
|
|
|
|
ERROR_PARSER_SPEC_JSON_INVALID, config->target, "/spec.json is invalid."
|
|
|
|
);
|
2023-11-23 20:31:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
free(filepath);
|
2023-11-25 16:15:30 +00:00
|
|
|
return error;
|
2023-11-23 20:31:54 +00:00
|
|
|
}
|
|
|
|
|
2023-11-25 16:15:30 +00:00
|
|
|
struct Error *parse_spec_json(
|
2023-11-25 02:35:22 +00:00
|
|
|
const struct Config *const config, cJSON **parsed
|
|
|
|
) {
|
2023-11-23 20:31:54 +00:00
|
|
|
FILE *handle = 0;
|
2023-11-25 16:15:30 +00:00
|
|
|
struct Error *error = find_spec_json(config, &handle);
|
2023-11-23 20:31:54 +00:00
|
|
|
|
2023-11-25 16:15:30 +00:00
|
|
|
if (error) {
|
|
|
|
return error;
|
2023-11-23 20:31:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// The `spec.json` file does not exist.
|
|
|
|
if (!handle) {
|
|
|
|
*parsed = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-11-23 22:01:58 +00:00
|
|
|
// For simplicity, load the entire file into memory.
|
|
|
|
fseek(handle, 0, SEEK_END);
|
|
|
|
size_t file_size = ftell(handle);
|
|
|
|
fseek(handle, 0, SEEK_SET);
|
|
|
|
char *fcontent = malloc(file_size);
|
|
|
|
size_t read_count = fread(fcontent, 1, file_size, handle);
|
|
|
|
assert(read_count == file_size);
|
|
|
|
|
|
|
|
*parsed = cJSON_Parse(fcontent);
|
|
|
|
|
|
|
|
free(fcontent);
|
2023-11-23 20:31:54 +00:00
|
|
|
fclose(handle);
|
2023-11-23 22:01:58 +00:00
|
|
|
|
|
|
|
// Can use `cJSON_GetErrorPtr()` to get the actual error message.
|
|
|
|
if (!*parsed) {
|
2023-11-25 16:15:30 +00:00
|
|
|
return ERROR_NEW(
|
|
|
|
ERROR_PARSER_SPEC_JSON_INVALID_SYNTAX,
|
|
|
|
"The spec.json file contains invalid JSON."
|
|
|
|
);
|
2023-11-23 22:01:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2023-11-23 20:31:54 +00:00
|
|
|
}
|