blob: 02dab7a38f5bf99d3ea8fc19a4edd9c9e374d496 [file] [log] [blame] [edit]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <json-c/json.h>
#include "validate.h"
json_object *json = NULL;
json_object *schema = NULL;
json_object *defs = NULL;
static char *schemavalidator_errstr[SCHEMAVALIDATOR_ERR_MAX] = {
"VALID",
"GENERAL ERROR",
"JSON FILE NOT FOUND",
"SCHEMA FILE NOT FOUND",
"WRONG ARGUEMNTS GIVEN",
"SCHEMA ERROR",
"INVALID",
"REGEX MISMATCH",
"REGEX MATCH",
"REGEX COMPILE FAILED"
};
const char *schemavalidator_errorstr(unsigned int schemavalidator_errors)
{
if (schemavalidator_errors < SCHEMAVALIDATOR_ERR_MAX) {
return schemavalidator_errstr[schemavalidator_errors];
}
return NULL;
}
int _schemavalidator_load(const char *jsonfile, const char *jsonschema)
{
json = json_object_from_file(jsonfile);
if (json == NULL) {
return SCHEMAVALIDATOR_ERR_JSON_NOT_FOUND;
}
schema = json_object_from_file(jsonschema);
if (schema == NULL) {
json_object_put(json);
return SCHEMAVALIDATOR_ERR_SCHEMA_NOT_FOUND;
}
return SCHEMAVALIDATOR_ERR_VALID;
}
int __schemavalidator_inspect_type(json_object *jobj, const char *type,
json_object *joutput_node)
{
if (strcmp(type, "object") == 0) {
if (json_object_is_type(jobj, json_type_object)) {
return SCHEMAVALIDATOR_ERR_VALID;
}
} else if (strcmp(type, "array") == 0) {
if (json_object_is_type(jobj, json_type_array)) {
return SCHEMAVALIDATOR_ERR_VALID;
}
} else if (strcmp(type, "string") == 0) {
if (json_object_is_type(jobj, json_type_string)) {
return SCHEMAVALIDATOR_ERR_VALID;
}
} else if (strcmp(type, "integer") == 0) {
if (json_object_is_type(jobj, json_type_int)) {
return SCHEMAVALIDATOR_ERR_VALID;
}
if (json_object_is_type(jobj, json_type_double)) {
double value = json_object_get_double(jobj);
if (value ==
round(value)) { // "zero fractional part is an integer"
return SCHEMAVALIDATOR_ERR_VALID;
}
}
} else if (strcmp(type, "double") == 0) {
if (json_object_is_type(jobj, json_type_double)) {
return SCHEMAVALIDATOR_ERR_VALID;
}
} else if (strcmp(type, "number") == 0) {
if (json_object_is_type(jobj, json_type_double) ||
json_object_is_type(jobj, json_type_int)) {
return SCHEMAVALIDATOR_ERR_VALID;
}
} else if (strcmp(type, "boolean") == 0) {
if (json_object_is_type(jobj, json_type_boolean)) {
return SCHEMAVALIDATOR_ERR_VALID;
}
} else if (strcmp(type, "null") == 0) {
if (json_object_is_type(jobj, json_type_null)) {
return SCHEMAVALIDATOR_ERR_VALID;
}
} else {
printf("WARN unknown type in check type %s\n", type);
json_object *jnode =
_schemavalidator_output_create_and_append_node(
joutput_node, "type");
_schemavalidator_output_apply_result(
jnode, SCHEMAVALIDATOR_ERR_SCHEMA_ERROR);
return SCHEMAVALIDATOR_ERR_SCHEMA_ERROR;
}
json_object *jnode = _schemavalidator_output_create_and_append_node(
joutput_node, "type");
_schemavalidator_output_apply_result(jnode,
SCHEMAVALIDATOR_ERR_INVALID);
return SCHEMAVALIDATOR_ERR_INVALID;
}
int schemavalidator_check_bool(json_object *jobj, json_object *jschema,
json_object *joutput_node)
{
(void)jobj;
// check if jschema is a bool, true or false
int err;
if (json_object_is_type(jschema, json_type_boolean)) {
json_object *jnode =
_schemavalidator_output_create_and_append_node(
joutput_node, "bool");
json_bool value = json_object_get_boolean(jschema);
err = value == 0 ? SCHEMAVALIDATOR_ERR_INVALID :
SCHEMAVALIDATOR_ERR_VALID;
_schemavalidator_output_apply_result(jnode, err);
return err;
}
return SCHEMAVALIDATOR_ERR_VALID;
}
int _schemavalidator_check_type(json_object *jobj, json_object *jschema,
json_object *joutput_node)
{
json_object *jnode;
json_object *jtype = json_object_object_get(jschema, "type");
if (jtype == NULL) {
return SCHEMAVALIDATOR_ERR_VALID;
}
if (json_object_is_type(jtype, json_type_string)) {
const char *type = json_object_get_string(jtype);
return __schemavalidator_inspect_type(jobj, type, joutput_node);
}
if (json_object_is_type(jtype, json_type_array)) {
int arraylen = json_object_array_length(jtype);
for (int i = 0; i < arraylen; i++) {
json_object *iobj = json_object_array_get_idx(jtype, i);
if (!json_object_is_type(iobj, json_type_string)) {
goto check_type_schema_error;
}
const char *type = json_object_get_string(iobj);
int err = __schemavalidator_inspect_type(jobj, type,
joutput_node);
if (err == SCHEMAVALIDATOR_ERR_VALID) {
return SCHEMAVALIDATOR_ERR_VALID;
}
}
jnode = _schemavalidator_output_create_and_append_node(
joutput_node, "type");
_schemavalidator_output_apply_result(
jnode, SCHEMAVALIDATOR_ERR_INVALID);
return SCHEMAVALIDATOR_ERR_INVALID;
}
check_type_schema_error:
jnode = _schemavalidator_output_create_and_append_node(joutput_node,
"type");
_schemavalidator_output_apply_result(jnode,
SCHEMAVALIDATOR_ERR_SCHEMA_ERROR);
return SCHEMAVALIDATOR_ERR_SCHEMA_ERROR;
}
int _schemavalidator_check_required(json_object *jobj, json_object *jschema,
json_object *joutput_node)
{
//printf("%s\n%s\n", __func__, json_object_to_json_string(jobj));
json_object *jarray = json_object_object_get(jschema, "required");
if (!jarray) {
return SCHEMAVALIDATOR_ERR_VALID;
}
json_object *jrequired_node =
_schemavalidator_output_create_and_append_node(joutput_node,
"required");
int missing_required_key = 0;
int arraylen = json_object_array_length(jarray);
for (int i = 0; i < arraylen; i++) {
json_object *iobj = json_object_array_get_idx(jarray, i);
const char *key = json_object_get_string(iobj);
if (key) {
//printf("%s\n", key);
// use json_object_object_get_ex becuase of json_type_null types
json_object *required_object = NULL;
int err = json_object_object_get_ex(jobj, key,
&required_object);
if (err == 0) {
// printf("required key missing: %s\n", key);
json_object *jkeynode =
_schemavalidator_output_create_and_append_node(
jrequired_node, key);
_schemavalidator_output_apply_result(
jkeynode, SCHEMAVALIDATOR_ERR_INVALID);
missing_required_key = 1;
}
}
}
int ret = missing_required_key == 1 ? SCHEMAVALIDATOR_ERR_INVALID :
SCHEMAVALIDATOR_ERR_VALID;
_schemavalidator_output_apply_result(jrequired_node, ret);
return ret;
}
int _schemavalidator_check_properties(json_object *jobj, json_object *jschema,
json_object *joutput_node)
{
// printf("%s\n", __func__);
json_object *jprops = json_object_object_get(jschema, "properties");
if (!jprops) {
return SCHEMAVALIDATOR_ERR_VALID;
}
json_object *jproperties_node =
_schemavalidator_output_create_and_append_node(joutput_node,
"properties");
int properties_valid = 1;
json_object_object_foreach(jprops, jprop_key, jprop_val)
{
// printf("key of prop is %s\n", jprop_key);
json_object *iobj = json_object_object_get(jobj, jprop_key);
//printf("iobj %s type %d\nkey %s\nval %s\n", json_object_get_string(iobj), json_object_get_type(iobj), jprop_key, json_object_get_string(jprop_val));
if (iobj) {
json_object *jprop_item_tmp_node =
_schemavalidator_output_create_node(jprop_key);
int err = _schemavalidator_validate_instance(
iobj, jprop_val, jprop_item_tmp_node);
if (err != SCHEMAVALIDATOR_ERR_VALID) {
properties_valid = 0;
_schemavalidator_output_apply_result(
jprop_item_tmp_node, err);
_schemavalidator_output_append_node(
jproperties_node, jprop_item_tmp_node);
} else {
json_object_put(jprop_item_tmp_node);
}
}
}
int ret = properties_valid == 1 ? SCHEMAVALIDATOR_ERR_VALID :
SCHEMAVALIDATOR_ERR_INVALID;
_schemavalidator_output_apply_result(jproperties_node, ret);
return ret;
}
int _schemavalidator_check_prefixItems_and_items(json_object *jobj,
json_object *jschema,
json_object *joutput_node)
{
json_object *jprefixitems =
json_object_object_get(jschema, "prefixItems");
json_object *jitems = json_object_object_get(jschema, "items");
int prefixitems_ok = 1;
int items_ok = 1;
if (jprefixitems) {
json_object *jprefixitems_node =
_schemavalidator_output_create_and_append_node(
joutput_node, "prefixItems");
if (!json_object_is_type(jprefixitems, json_type_array)) {
_schemavalidator_output_apply_result(
jprefixitems_node,
SCHEMAVALIDATOR_ERR_SCHEMA_ERROR);
return SCHEMAVALIDATOR_ERR_SCHEMA_ERROR;
}
int jobj_arraylen = json_object_array_length(jobj);
int prefixitems_arraylen =
json_object_array_length(jprefixitems);
for (int i = 0; i < jobj_arraylen && i < prefixitems_arraylen;
i++) {
//printf("i=%d prefixitems\n", i);
json_object *iobj = json_object_array_get_idx(jobj, i);
json_object *ischema =
json_object_array_get_idx(jprefixitems, i);
char numstr[12];
snprintf(numstr, sizeof(numstr), "%d", i);
json_object *jarrayitem_tmp_node =
_schemavalidator_output_create_node(numstr);
int err = _schemavalidator_validate_instance(
iobj, ischema, jarrayitem_tmp_node);
if (err) {
_schemavalidator_output_apply_result(
jprefixitems_node, err);
_schemavalidator_output_append_node(
jprefixitems_node, jarrayitem_tmp_node);
prefixitems_ok = 0;
} else {
json_object_put(jarrayitem_tmp_node);
}
}
int prefixitems_ret = (prefixitems_ok == 1) ?
SCHEMAVALIDATOR_ERR_VALID :
SCHEMAVALIDATOR_ERR_INVALID;
_schemavalidator_output_apply_result(jprefixitems_node,
prefixitems_ret);
}
if (jitems) {
json_object *jitems_node =
_schemavalidator_output_create_and_append_node(
joutput_node, "items");
if (!json_object_is_type(jitems, json_type_object) &&
!json_object_is_type(jitems, json_type_boolean)) {
_schemavalidator_output_apply_result(
jitems_node, SCHEMAVALIDATOR_ERR_SCHEMA_ERROR);
return SCHEMAVALIDATOR_ERR_SCHEMA_ERROR;
}
int jobj_arraylen = json_object_array_length(jobj);
int items_arraylen = 0;
for (int i = items_arraylen; i < jobj_arraylen; i++) {
//printf("i=%d items\n", i);
json_object *iobj = json_object_array_get_idx(jobj, i);
char numstr[12];
snprintf(numstr, sizeof(numstr), "%d", i);
json_object *jarrayitem_tmp_node =
_schemavalidator_output_create_node(numstr);
int err = _schemavalidator_validate_instance(
iobj, jitems, jarrayitem_tmp_node);
if (err) {
_schemavalidator_output_apply_result(
jarrayitem_tmp_node, err);
_schemavalidator_output_append_node(
jitems_node, jarrayitem_tmp_node);
items_ok = 0;
} else {
json_object_put(jarrayitem_tmp_node);
}
}
int items_ret = (items_ok == 1) ? SCHEMAVALIDATOR_ERR_VALID :
SCHEMAVALIDATOR_ERR_INVALID;
_schemavalidator_output_apply_result(jitems_node, items_ret);
}
int ret = (prefixitems_ok == 1 && items_ok == 1) ?
SCHEMAVALIDATOR_ERR_VALID :
SCHEMAVALIDATOR_ERR_INVALID;
return ret;
}
int _schemavalidator_value_is_equal(json_object *jobj1, json_object *jobj2)
{
if (json_object_equal(jobj1, jobj2)) {
return SCHEMAVALIDATOR_ERR_VALID;
}
if (json_object_is_type(jobj1, json_type_double) &&
json_object_is_type(jobj2, json_type_int)) {
double value = json_object_get_double(jobj1);
double value2 = json_object_get_int64(jobj2);
if (value == round(value) && value == value2) {
return SCHEMAVALIDATOR_ERR_VALID;
}
}
if (json_object_is_type(jobj1, json_type_int) &&
json_object_is_type(jobj2, json_type_double)) {
double value = json_object_get_double(jobj2);
double value2 = json_object_get_int64(jobj1);
if (value == round(value) && value == value2) {
return SCHEMAVALIDATOR_ERR_VALID;
}
}
return SCHEMAVALIDATOR_ERR_INVALID;
}
int _schemavalidator_check_const(json_object *jobj, json_object *jschema,
json_object *joutput_node)
{
json_object *jconst;
int err = json_object_object_get_ex(jschema, "const", &jconst);
if (err == 0) {
return SCHEMAVALIDATOR_ERR_VALID;
}
err = _schemavalidator_value_is_equal(jobj, jconst);
if (err == SCHEMAVALIDATOR_ERR_VALID) {
return SCHEMAVALIDATOR_ERR_VALID;
}
json_object *jnode = _schemavalidator_output_create_and_append_node(
joutput_node, "const");
_schemavalidator_output_apply_result(jnode,
SCHEMAVALIDATOR_ERR_INVALID);
return SCHEMAVALIDATOR_ERR_INVALID;
}
int _schemavalidator_check_enums(json_object *jobj, json_object *jschema,
json_object *joutput_node)
{
json_object *jenum_array = json_object_object_get(jschema, "enum");
if (!jenum_array) {
return SCHEMAVALIDATOR_ERR_VALID;
}
if (!json_object_is_type(jenum_array, json_type_array)) {
json_object *jnode =
_schemavalidator_output_create_and_append_node(
joutput_node, "enum");
_schemavalidator_output_apply_result(
jnode, SCHEMAVALIDATOR_ERR_SCHEMA_ERROR);
return SCHEMAVALIDATOR_ERR_SCHEMA_ERROR;
}
int arraylen = json_object_array_length(jenum_array);
for (int i = 0; i < arraylen; i++) {
json_object *ienum = json_object_array_get_idx(jenum_array, i);
int err = _schemavalidator_value_is_equal(jobj, ienum);
if (err == SCHEMAVALIDATOR_ERR_VALID) {
return SCHEMAVALIDATOR_ERR_VALID;
}
}
// printf("ERROR: enum check failed (%s not in enum)\n", json_object_to_json_string(jobj));
json_object *jnode = _schemavalidator_output_create_and_append_node(
joutput_node, "enum");
_schemavalidator_output_apply_result(jnode,
SCHEMAVALIDATOR_ERR_INVALID);
return SCHEMAVALIDATOR_ERR_INVALID;
}
int _schemavalidator_check_uniqueItems(json_object *jobj, json_object *jschema,
json_object *joutput_node)
{
json_object *juniq = json_object_object_get(jschema, "uniqueItems");
if (!juniq) {
return SCHEMAVALIDATOR_ERR_VALID;
}
json_object *juniqueitems_node =
_schemavalidator_output_create_and_append_node(joutput_node,
"uniqueItems");
if (!json_object_is_type(juniq, json_type_boolean)) {
_schemavalidator_output_apply_result(
juniqueitems_node, SCHEMAVALIDATOR_ERR_SCHEMA_ERROR);
return SCHEMAVALIDATOR_ERR_SCHEMA_ERROR;
}
// uniqueItems=false is valid
if (json_object_get_boolean(juniq) == 0) {
_schemavalidator_output_apply_result(juniqueitems_node,
SCHEMAVALIDATOR_ERR_VALID);
return SCHEMAVALIDATOR_ERR_VALID;
}
int uniqueitems_ok = 1;
int arraylen = json_object_array_length(jobj);
for (int i = 0; i < arraylen - 1; i++) {
json_object *iobj = json_object_array_get_idx(jobj, i);
for (int j = i + 1; j < arraylen; j++) {
json_object *uobj = json_object_array_get_idx(jobj, j);
if (json_object_equal(iobj, uobj) == 1) {
uniqueitems_ok = 0;
char numstr[12];
snprintf(numstr, sizeof(numstr), "%d", i);
json_object *jnotunique_node =
_schemavalidator_output_create_and_append_node(
juniqueitems_node, numstr);
_schemavalidator_output_apply_result(
jnotunique_node,
SCHEMAVALIDATOR_ERR_INVALID);
}
}
}
int ret = uniqueitems_ok == 1 ? SCHEMAVALIDATOR_ERR_VALID :
SCHEMAVALIDATOR_ERR_INVALID;
_schemavalidator_output_apply_result(juniqueitems_node, ret);
return ret;
}
int _schemavalidator_check_maxmin_items(json_object *jobj, json_object *jschema,
json_object *joutput_node)
{
int err = SCHEMAVALIDATOR_ERR_VALID;
int arraylen = json_object_array_length(jobj);
json_object *jmax = json_object_object_get(jschema, "maxItems");
if (jmax) {
if (json_object_is_type(jmax, json_type_int) ||
json_object_is_type(jmax, json_type_double)) {
int maxitems = json_object_get_double(jmax);
if (arraylen > maxitems) {
json_object *jmaxitems_node =
_schemavalidator_output_create_and_append_node(
joutput_node, "maxItems");
_schemavalidator_output_apply_result(
jmaxitems_node,
SCHEMAVALIDATOR_ERR_INVALID);
err = SCHEMAVALIDATOR_ERR_INVALID;
}
}
}
json_object *jmin = json_object_object_get(jschema, "minItems");
if (jmin) {
if (json_object_is_type(jmin, json_type_int) ||
json_object_is_type(jmin, json_type_double)) {
int minitems = json_object_get_double(jmin);
if (arraylen < minitems) {
json_object *jminitems_node =
_schemavalidator_output_create_and_append_node(
joutput_node, "minItems");
_schemavalidator_output_apply_result(
jminitems_node,
SCHEMAVALIDATOR_ERR_INVALID);
err = SCHEMAVALIDATOR_ERR_INVALID;
}
}
}
// if (err)
// printf("ERROR: failed at maxItems or minItems check\n");
return err;
}
int _schemavalidator_validate_array(json_object *jobj, json_object *jschema,
json_object *joutput_node)
{
int err;
err = _schemavalidator_check_prefixItems_and_items(jobj, jschema,
joutput_node);
if (err) {
return err;
}
err = _schemavalidator_check_uniqueItems(jobj, jschema, joutput_node);
if (err) {
return err;
}
err = _schemavalidator_check_maxmin_items(jobj, jschema, joutput_node);
if (err) {
return err;
}
return SCHEMAVALIDATOR_ERR_VALID;
}
int _schemavalidator_validate_object(json_object *jobj, json_object *jschema,
json_object *joutput_node)
{
int err;
if (defs == NULL) {
defs = json_object_object_get(jschema, "$defs");
}
err = _schemavalidator_check_required(jobj, jschema, joutput_node);
if (err) {
return err;
}
err = _schemavalidator_check_properties(jobj, jschema, joutput_node);
if (err) {
return err;
}
return SCHEMAVALIDATOR_ERR_VALID;
}
int utf8_length(const char *str)
{
const char *pointer = str;
int len = 0;
while (pointer[0]) {
if ((pointer[0] & 0xC0) != 0x80) {
len++;
}
pointer++;
}
return len;
}
int _schemavalidator_validate_string(json_object *jobj, json_object *jschema,
json_object *joutput_node)
{
const char *str = json_object_get_string(jobj);
//printf("strlen of %s %ld %d %d\n", str, strlen(str), json_object_get_string_len(jobj), utf8_length(str));
int minlength_ok = 1;
json_object *jminlen = json_object_object_get(jschema, "minLength");
if (jminlen) {
int minlen = json_object_get_int64(jminlen);
if (utf8_length(str) < minlen) {
minlength_ok = 0;
json_object *jminlength_node =
_schemavalidator_output_create_and_append_node(
joutput_node, "minLength");
_schemavalidator_output_apply_result(
jminlength_node, SCHEMAVALIDATOR_ERR_INVALID);
}
}
int maxlength_ok = 1;
json_object *jmaxlen = json_object_object_get(jschema, "maxLength");
if (jmaxlen) {
int maxlen = json_object_get_int64(jmaxlen);
if (utf8_length(str) > maxlen) {
maxlength_ok = 0;
json_object *jmaxlength_node =
_schemavalidator_output_create_and_append_node(
joutput_node, "maxLength");
_schemavalidator_output_apply_result(
jmaxlength_node, SCHEMAVALIDATOR_ERR_INVALID);
}
}
int enums_ok = 1;
int err = _schemavalidator_check_enums(jobj, jschema, joutput_node);
if (err) {
if (err == SCHEMAVALIDATOR_ERR_SCHEMA_ERROR) {
// _schemavalidator_output_apply_result(joutput_node, SCHEMAVALIDATOR_ERR_SCHEMA_ERROR);
return err;
}
enums_ok = 0;
}
int ret = minlength_ok == 1 && maxlength_ok == 1 && enums_ok == 1 ?
SCHEMAVALIDATOR_ERR_VALID :
SCHEMAVALIDATOR_ERR_INVALID;
// _schemavalidator_output_apply_result(joutput_node, ret);
return ret;
}
int _schemavalidator_validate_integer(json_object *jobj, json_object *jschema,
json_object *joutput_node)
{
(void)jobj;
double value = (double)json_object_get_int64(jobj);
int err = _schemavalidator_validate_number(jobj, jschema, value,
joutput_node);
return err;
}
int _schemavalidator_validate_double(json_object *jobj, json_object *jschema,
json_object *joutput_node)
{
(void)jobj;
double value = json_object_get_double(jobj);
int err = _schemavalidator_validate_number(jobj, jschema, value,
joutput_node);
return err;
}
int _schemavalidator_validate_number(json_object *jobj, json_object *jschema,
double value, json_object *joutput_node)
{
(void)jobj;
int multipleOf_ok = 1;
json_object *jmult = json_object_object_get(jschema, "multipleOf");
if (jmult) {
double multipland = (double)json_object_get_double(jmult);
if (multipland == 0.0) {
json_object *jmultipleOf_node =
_schemavalidator_output_create_and_append_node(
joutput_node, "multipleOf");
_schemavalidator_output_apply_result(
jmultipleOf_node,
SCHEMAVALIDATOR_ERR_SCHEMA_ERROR);
// _schemavalidator_output_apply_result(joutput_node, SCHEMAVALIDATOR_ERR_SCHEMA_ERROR);
return SCHEMAVALIDATOR_ERR_SCHEMA_ERROR;
}
double divided = value / multipland;
if (isinf(divided) != 0 || divided != round(divided)) {
multipleOf_ok = 0;
}
if (multipleOf_ok == 0) {
json_object *jmultipleOf_node =
_schemavalidator_output_create_and_append_node(
joutput_node, "multipleOf");
_schemavalidator_output_apply_result(
jmultipleOf_node, SCHEMAVALIDATOR_ERR_INVALID);
}
}
int minimum_ok = 1;
json_object *jmin = json_object_object_get(jschema, "minimum");
if (jmin) {
double min = (double)json_object_get_double(jmin);
if (value < min) {
minimum_ok = 0;
json_object *jminimum_node =
_schemavalidator_output_create_and_append_node(
joutput_node, "minimum");
_schemavalidator_output_apply_result(
jminimum_node, SCHEMAVALIDATOR_ERR_INVALID);
}
}
int exclusiveMinimum_ok = 1;
json_object *jexclmin =
json_object_object_get(jschema, "exclusiveMinimum");
if (jexclmin) {
double min = (double)json_object_get_double(jexclmin);
if (value <= min) {
exclusiveMinimum_ok = 0;
json_object *jexclusiveMinimum_node =
_schemavalidator_output_create_and_append_node(
joutput_node, "exclusiveMinimum");
_schemavalidator_output_apply_result(
jexclusiveMinimum_node,
SCHEMAVALIDATOR_ERR_INVALID);
}
}
int maximum_ok = 1;
json_object *jmax = json_object_object_get(jschema, "maximum");
if (jmax) {
double max = (double)json_object_get_double(jmax);
if (value > max) {
maximum_ok = 0;
json_object *jmaximum_node =
_schemavalidator_output_create_and_append_node(
joutput_node, "maximum");
_schemavalidator_output_apply_result(
jmaximum_node, SCHEMAVALIDATOR_ERR_INVALID);
}
}
int exclusiveMaximum_ok = 1;
json_object *jexclmax =
json_object_object_get(jschema, "exclusiveMaximum");
if (jexclmax) {
double max = (double)json_object_get_double(jexclmax);
if (value >= max) {
exclusiveMaximum_ok = 0;
json_object *jexclusiveMaximum_node =
_schemavalidator_output_create_and_append_node(
joutput_node, "exclusiveMaximum");
_schemavalidator_output_apply_result(
jexclusiveMaximum_node,
SCHEMAVALIDATOR_ERR_INVALID);
}
}
int ret = multipleOf_ok == 1 && minimum_ok == 1 &&
exclusiveMinimum_ok == 1 && maximum_ok == 1 &&
exclusiveMaximum_ok == 1 ?
SCHEMAVALIDATOR_ERR_VALID :
SCHEMAVALIDATOR_ERR_INVALID;
// _schemavalidator_output_apply_result(joutput_node, ret);
return ret;
}
int _schemavalidator_validate_boolean(json_object *jobj, json_object *jschema,
json_object *joutput_node)
{
(void)jobj;
(void)jschema;
(void)joutput_node;
// printf("%s\n", __func__);
// _schemavalidator_output_apply_result(joutput_node, SCHEMAVALIDATOR_ERR_VALID);
return SCHEMAVALIDATOR_ERR_VALID;
}
int _schemavalidator_validate_instance(json_object *jobj, json_object *jschema,
json_object *joutput_node)
{
int err;
// printf("--validate instance--\n");
// printf("%s\n", json_object_get_string(jobj));
// printf("%s\n", json_object_get_string(jschema));
err = schemavalidator_check_bool(jobj, jschema, joutput_node);
if (err) {
return err;
}
err = _schemavalidator_check_type(jobj, jschema, joutput_node);
if (err) {
return err;
}
err = _schemavalidator_check_const(jobj, jschema, joutput_node);
if (err) {
return err;
}
err = _schemavalidator_check_enums(jobj, jschema, joutput_node);
if (err) {
return err;
}
json_type type = json_object_get_type(jobj);
if (type == json_type_object) {
return _schemavalidator_validate_object(jobj, jschema,
joutput_node);
}
if (type == json_type_array) {
return _schemavalidator_validate_array(jobj, jschema,
joutput_node);
}
if (type == json_type_string) {
return _schemavalidator_validate_string(jobj, jschema,
joutput_node);
}
if (type == json_type_boolean) {
return _schemavalidator_validate_boolean(jobj, jschema,
joutput_node);
}
if (type == json_type_int) {
return _schemavalidator_validate_integer(jobj, jschema,
joutput_node);
}
if (type == json_type_double) {
return _schemavalidator_validate_double(jobj, jschema,
joutput_node);
}
if (type == json_type_null) {
return SCHEMAVALIDATOR_ERR_VALID;
}
printf("%s: WARN: type %d not handled\n", __func__, type);
return SCHEMAVALIDATOR_ERR_VALID;
}
int schemavalidator_validate(json_object *jobj, json_object *jschema)
{
json_object *joutput = _schemavalidator_output_create_node("root");
int err = _schemavalidator_validate_instance(jobj, jschema, joutput);
_schemavalidator_output_apply_result(joutput, err);
if (joutput) {
//printf("Basic Output: %s\n", json_object_get_string(joutput));
_schemavalidator_output_print_errors(joutput);
}
if (joutput) {
json_object_put(joutput);
}
return err;
}