You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

118 lines
3.4 KiB

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "json.h"
#include "route_config_parse.h"
#include "tenant_config.h"
enum
{
tenant_config_json_key_name,
tenant_config_json_key_port,
tenant_config_json_key_routes,
tenant_config_json_key_len
};
static const char *tenant_config_json_keys[tenant_config_json_key_len] = { "name", "port", "routes" };
/* Tenant Config */
static inline int
tenant_config_parse(struct tenant_config *config, const char *json_buf, jsmntok_t *tokens, size_t tokens_base,
int tokens_size)
{
int i = tokens_base;
char key[32] = { 0 };
if (!has_valid_type(tokens[i], "Anonymous Tenant Config Object", JSMN_OBJECT, json_buf)) return -1;
if (!is_nonempty_object(tokens[i], "Anonymous Tenant Config Object")) return -1;
int tenant_key_count = tokens[i].size;
for (int tenant_key_idx = 0; tenant_key_idx < tenant_key_count; tenant_key_idx++) {
/* Advance to key */
i++;
if (!is_valid_key(tokens[i])) return -1;
if (!has_valid_size(tokens[i], key, 1)) return -1;
/* Copy Key */
sprintf(key, "%.*s", tokens[i].end - tokens[i].start, json_buf + tokens[i].start);
/* Advance to Value */
i++;
if (strcmp(key, tenant_config_json_keys[tenant_config_json_key_name]) == 0) {
if (!is_nonempty_string(tokens[i], key)) return -1;
config->name = strndup(json_buf + tokens[i].start, tokens[i].end - tokens[i].start);
} else if (strcmp(key, tenant_config_json_keys[tenant_config_json_key_port]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
int rc = parse_uint16_t(tokens[i], json_buf,
tenant_config_json_keys[tenant_config_json_key_port], &config->port);
if (rc < 0) return -1;
} else if (strcmp(key, tenant_config_json_keys[tenant_config_json_key_routes]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_ARRAY, json_buf)) return -1;
int routes_len = tokens[i].size;
config->routes_len = routes_len;
config->routes = (struct route_config *)calloc(routes_len, sizeof(struct route_config));
for (int route_idx = 0; route_idx < routes_len; route_idx++) {
/* Advance to object */
i++;
i = route_config_parse(&(config->routes)[route_idx], json_buf, tokens, i, tokens_size);
if (i == -1) return -1;
}
} else {
fprintf(stderr, "%s is not a valid key\n", key);
return -1;
}
}
return i;
}
/* Tenant Config Vec */
static inline int
tenant_config_vec_parse(struct tenant_config **tenant_config_vec, int *tenant_config_vec_len, const char *json_buf,
jsmntok_t *tokens, size_t tokens_base, int tokens_size)
{
int i = tokens_base;
if (tokens[i].type != JSMN_ARRAY) {
fprintf(stderr, "Outermost Config should be a JSON array, was a JSON %s\n", jsmn_type(tokens[0].type));
return -1;
}
*tenant_config_vec_len = tokens[i].size;
if (tenant_config_vec_len == 0) {
fprintf(stderr, "Config is an empty JSON array\n");
return -1;
}
*tenant_config_vec = (struct tenant_config *)calloc((size_t)(*tenant_config_vec_len),
sizeof(struct tenant_config));
if (*tenant_config_vec == NULL) {
perror("Failed to allocate vec");
return -1;
}
for (int tenant_idx = 0; tenant_idx < *tenant_config_vec_len; tenant_idx++) {
i++;
i = tenant_config_parse(&((*tenant_config_vec)[tenant_idx]), json_buf, tokens, i, tokens_size);
if (i == -1) return -1;
}
return i;
}